Merge
This commit is contained in:
commit
38c494e569
@ -200,3 +200,4 @@ b43aa5bd8ca5c8121336495382d35ecfa7a71536 jdk8-b74
|
|||||||
278af9fc67e7eba2884936b49ec07345f423aabb jdk8-b76
|
278af9fc67e7eba2884936b49ec07345f423aabb jdk8-b76
|
||||||
3933eebc659d58c597aa8cb4b3e58f2250ce3e1a jdk8-b77
|
3933eebc659d58c597aa8cb4b3e58f2250ce3e1a jdk8-b77
|
||||||
fd1a5574cf68af24bfd52decc37ac6361afb278a jdk8-b78
|
fd1a5574cf68af24bfd52decc37ac6361afb278a jdk8-b78
|
||||||
|
91d35211e74464dca5edf9b66ab01d0d0d8cded7 jdk8-b79
|
||||||
|
39
README
39
README
@ -1,45 +1,40 @@
|
|||||||
README:
|
README:
|
||||||
This file should be located at the top of the OpenJDK Mercurial root
|
This file should be located at the top of the OpenJDK Mercurial root
|
||||||
repository. This root repository will include a "make" directory,
|
repository. A full OpenJDK repository set (forest) should also include
|
||||||
and a Makefile for building the entire OpenJDK.
|
the following 6 nested repositories:
|
||||||
A full OpenJDK repository set (forest) should also include the following
|
|
||||||
6 nested repositories:
|
|
||||||
"jdk", "hotspot", "langtools", "corba", "jaxws" and "jaxp".
|
"jdk", "hotspot", "langtools", "corba", "jaxws" and "jaxp".
|
||||||
There are also several source downloads for the jax* repositories that
|
|
||||||
will be needed.
|
|
||||||
|
|
||||||
This one root repository can be obtained with something like:
|
|
||||||
|
|
||||||
|
The root repository can be obtained with something like:
|
||||||
hg clone http://hg.openjdk.java.net/jdk8/jdk8 openjdk8
|
hg clone http://hg.openjdk.java.net/jdk8/jdk8 openjdk8
|
||||||
|
|
||||||
To make sure you have all the nested repositories, you can run the
|
You can run the get_source.sh script located in the root repository to get
|
||||||
get_source.sh script located in the same respository as this file:
|
the other needed repositories:
|
||||||
|
|
||||||
cd openjdk8 && sh ./get_source.sh
|
cd openjdk8 && sh ./get_source.sh
|
||||||
|
|
||||||
People unfamiliar with Mercurial should read the first few chapters of
|
People unfamiliar with Mercurial should read the first few chapters of
|
||||||
the Mercurial book: http://hgbook.red-bean.com/read/
|
the Mercurial book: http://hgbook.red-bean.com/read/
|
||||||
|
|
||||||
See http://openjdk.java.net/ for more information about the OpenJDK.
|
See http://openjdk.java.net/ for more information about OpenJDK.
|
||||||
|
|
||||||
Simple Build Instructions:
|
Simple Build Instructions:
|
||||||
|
|
||||||
0. Get the necessary system software/packages installed on your system, see
|
0. Get the necessary system software/packages installed on your system, see
|
||||||
http://hg.openjdk.java.net/jdk8/build/raw-file/tip/README-builds.html
|
http://hg.openjdk.java.net/jdk8/jdk8/raw-file/tip/README-builds.html
|
||||||
|
|
||||||
1. If you don't have a jdk6 installed, download and install a JDK 6 from
|
1. If you don't have a jdk7u7 or newer jdk, download and install it from
|
||||||
http://java.sun.com/javase/downloads/index.jsp
|
http://java.sun.com/javase/downloads/index.jsp
|
||||||
Set the environment variable ALT_BOOTDIR to the location of JDK 6.
|
Add the /bin directory of this installation to your PATH environment
|
||||||
|
variable.
|
||||||
|
|
||||||
2. Check the sanity of doing a build with your current system:
|
2. Configure the build:
|
||||||
make sanity
|
bash ./configure
|
||||||
See README-builds.html if you run into problems.
|
|
||||||
|
|
||||||
3. Do a complete build of the OpenJDK:
|
3. Build the OpenJDK:
|
||||||
make all
|
make all
|
||||||
The resulting JDK image should be found in build/*/j2sdk-image
|
The resulting JDK image should be found in build/*/images/j2sdk-image
|
||||||
|
|
||||||
where make is GNU make 3.81 or newer, /usr/bin/make on Linux usually
|
where make is GNU make 3.81 or newer, /usr/bin/make on Linux usually
|
||||||
is 3.81 or newer.
|
is 3.81 or newer. Note that on Solaris, GNU make is called "gmake".
|
||||||
|
|
||||||
Complete details are available in README-builds.html.
|
Complete details are available in the file:
|
||||||
|
http://hg.openjdk.java.net/jdk8/jdk8/raw-file/tip/README-builds.html
|
||||||
|
4480
README-builds.html
4480
README-builds.html
File diff suppressed because it is too large
Load Diff
@ -47,10 +47,6 @@ AC_DEFUN([BPERF_CHECK_CORES],
|
|||||||
FOUND_CORES=yes
|
FOUND_CORES=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# For c/c++ code we run twice as many concurrent build
|
|
||||||
# jobs than we have cores, otherwise we will stall on io.
|
|
||||||
CONCURRENT_BUILD_JOBS=`expr $NUM_CORES \* 2`
|
|
||||||
|
|
||||||
if test "x$FOUND_CORES" = xyes; then
|
if test "x$FOUND_CORES" = xyes; then
|
||||||
AC_MSG_RESULT([$NUM_CORES])
|
AC_MSG_RESULT([$NUM_CORES])
|
||||||
else
|
else
|
||||||
@ -98,32 +94,62 @@ AC_DEFUN([BPERF_CHECK_MEMORY_SIZE],
|
|||||||
|
|
||||||
AC_DEFUN_ONCE([BPERF_SETUP_BUILD_CORES],
|
AC_DEFUN_ONCE([BPERF_SETUP_BUILD_CORES],
|
||||||
[
|
[
|
||||||
# How many cores do we have on this build system?
|
# How many cores do we have on this build system?
|
||||||
AC_ARG_WITH(num-cores, [AS_HELP_STRING([--with-num-cores],
|
AC_ARG_WITH(num-cores, [AS_HELP_STRING([--with-num-cores],
|
||||||
[number of cores in the build system, e.g. --with-num-cores=8 @<:@probed@:>@])])
|
[number of cores in the build system, e.g. --with-num-cores=8 @<:@probed@:>@])])
|
||||||
if test "x$with_num_cores" = x; then
|
if test "x$with_num_cores" = x; then
|
||||||
# The number of cores were not specified, try to probe them.
|
# The number of cores were not specified, try to probe them.
|
||||||
BPERF_CHECK_CORES
|
BPERF_CHECK_CORES
|
||||||
else
|
else
|
||||||
NUM_CORES=$with_num_cores
|
NUM_CORES=$with_num_cores
|
||||||
CONCURRENT_BUILD_JOBS=`expr $NUM_CORES \* 2`
|
fi
|
||||||
fi
|
AC_SUBST(NUM_CORES)
|
||||||
AC_SUBST(NUM_CORES)
|
|
||||||
AC_SUBST(CONCURRENT_BUILD_JOBS)
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([BPERF_SETUP_BUILD_MEMORY],
|
AC_DEFUN_ONCE([BPERF_SETUP_BUILD_MEMORY],
|
||||||
[
|
[
|
||||||
# How much memory do we have on this build system?
|
# How much memory do we have on this build system?
|
||||||
AC_ARG_WITH(memory-size, [AS_HELP_STRING([--with-memory-size],
|
AC_ARG_WITH(memory-size, [AS_HELP_STRING([--with-memory-size],
|
||||||
[memory (in MB) available in the build system, e.g. --with-memory-size=1024 @<:@probed@:>@])])
|
[memory (in MB) available in the build system, e.g. --with-memory-size=1024 @<:@probed@:>@])])
|
||||||
if test "x$with_memory_size" = x; then
|
if test "x$with_memory_size" = x; then
|
||||||
# The memory size was not specified, try to probe it.
|
# The memory size was not specified, try to probe it.
|
||||||
BPERF_CHECK_MEMORY_SIZE
|
BPERF_CHECK_MEMORY_SIZE
|
||||||
else
|
else
|
||||||
MEMORY_SIZE=$with_memory_size
|
MEMORY_SIZE=$with_memory_size
|
||||||
fi
|
fi
|
||||||
AC_SUBST(MEMORY_SIZE)
|
AC_SUBST(MEMORY_SIZE)
|
||||||
|
])
|
||||||
|
|
||||||
|
AC_DEFUN_ONCE([BPERF_SETUP_BUILD_JOBS],
|
||||||
|
[
|
||||||
|
# Provide a decent default number of parallel jobs for make depending on
|
||||||
|
# number of cores, amount of memory and machine architecture.
|
||||||
|
AC_ARG_WITH(jobs, [AS_HELP_STRING([--with-jobs],
|
||||||
|
[number of parallel jobs to let make run @<:@calculated based on cores and memory@:>@])])
|
||||||
|
if test "x$with_jobs" = x; then
|
||||||
|
# Number of jobs was not specified, calculate.
|
||||||
|
AC_MSG_CHECKING([for appropriate number of jobs to run in parallel])
|
||||||
|
# Approximate memory in GB, rounding up a bit.
|
||||||
|
memory_gb=`expr $MEMORY_SIZE / 1100`
|
||||||
|
# Pick the lowest of memory in gb and number of cores.
|
||||||
|
if test "$memory_gb" -lt "$NUM_CORES"; then
|
||||||
|
JOBS="$memory_gb"
|
||||||
|
else
|
||||||
|
JOBS="$NUM_CORES"
|
||||||
|
# On bigger machines, leave some room for other processes to run
|
||||||
|
if test "$JOBS" -gt "4"; then
|
||||||
|
JOBS=`expr $JOBS '*' 90 / 100`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# Cap number of jobs to 16
|
||||||
|
if test "$JOBS" -gt "16"; then
|
||||||
|
JOBS=16
|
||||||
|
fi
|
||||||
|
AC_MSG_RESULT([$JOBS])
|
||||||
|
else
|
||||||
|
JOBS=$with_jobs
|
||||||
|
fi
|
||||||
|
AC_SUBST(JOBS)
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([BPERF_SETUP_CCACHE],
|
AC_DEFUN([BPERF_SETUP_CCACHE],
|
||||||
|
@ -204,6 +204,7 @@ JDKOPT_SETUP_BUILD_TWEAKS
|
|||||||
|
|
||||||
BPERF_SETUP_BUILD_CORES
|
BPERF_SETUP_BUILD_CORES
|
||||||
BPERF_SETUP_BUILD_MEMORY
|
BPERF_SETUP_BUILD_MEMORY
|
||||||
|
BPERF_SETUP_BUILD_JOBS
|
||||||
|
|
||||||
# Setup smart javac (after cores and memory have been setup)
|
# Setup smart javac (after cores and memory have been setup)
|
||||||
BPERF_SETUP_SMART_JAVAC
|
BPERF_SETUP_SMART_JAVAC
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -174,7 +174,7 @@ printf "* C++ Compiler: $CXX_VENDOR version $CXX_VERSION (at $CXX)\n"
|
|||||||
|
|
||||||
printf "\n"
|
printf "\n"
|
||||||
printf "Build performance summary:\n"
|
printf "Build performance summary:\n"
|
||||||
printf "* Cores to use: $NUM_CORES\n"
|
printf "* Cores to use: $JOBS\n"
|
||||||
printf "* Memory limit: $MEMORY_SIZE MB\n"
|
printf "* Memory limit: $MEMORY_SIZE MB\n"
|
||||||
printf "* ccache status: $CCACHE_STATUS\n"
|
printf "* ccache status: $CCACHE_STATUS\n"
|
||||||
printf "\n"
|
printf "\n"
|
||||||
|
@ -80,7 +80,7 @@ ALT_EXPORT_PATH=$(HOTSPOT_DIST)
|
|||||||
|
|
||||||
HOTSPOT_MAKE_ARGS:=@HOTSPOT_MAKE_ARGS@ @STATIC_CXX_SETTING@
|
HOTSPOT_MAKE_ARGS:=@HOTSPOT_MAKE_ARGS@ @STATIC_CXX_SETTING@
|
||||||
# This is used from the libjvm build for C/C++ code.
|
# This is used from the libjvm build for C/C++ code.
|
||||||
HOTSPOT_BUILD_JOBS:=@CONCURRENT_BUILD_JOBS@
|
HOTSPOT_BUILD_JOBS:=$(JOBS)
|
||||||
# Control wether Hotspot runs Queens test after building
|
# Control wether Hotspot runs Queens test after building
|
||||||
TEST_IN_BUILD=@TEST_IN_BUILD@
|
TEST_IN_BUILD=@TEST_IN_BUILD@
|
||||||
|
|
||||||
|
@ -260,6 +260,9 @@ ENABLE_SJAVAC:=@ENABLE_SJAVAC@
|
|||||||
# the sjavac server log files.
|
# the sjavac server log files.
|
||||||
SJAVAC_SERVER_DIR:=@SJAVAC_SERVER_DIR@
|
SJAVAC_SERVER_DIR:=@SJAVAC_SERVER_DIR@
|
||||||
|
|
||||||
|
# Number of parallel jobs to use for compilation
|
||||||
|
JOBS?=@JOBS@
|
||||||
|
|
||||||
# The OpenJDK makefiles should be changed to using the standard
|
# The OpenJDK makefiles should be changed to using the standard
|
||||||
# configure output ..._CFLAGS and ..._LIBS. In the meantime we
|
# configure output ..._CFLAGS and ..._LIBS. In the meantime we
|
||||||
# extract the information here.
|
# extract the information here.
|
||||||
@ -283,7 +286,7 @@ X_LIBS:=@X_LIBS@
|
|||||||
OPENWIN_HOME:=@OPENWIN_HOME@
|
OPENWIN_HOME:=@OPENWIN_HOME@
|
||||||
|
|
||||||
# The lowest required version of macosx to enforce compatiblity for
|
# The lowest required version of macosx to enforce compatiblity for
|
||||||
MACOSX_REQUIRED_VERSION=@MACOSX_REQUIRED_VERSION@
|
MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@
|
||||||
|
|
||||||
# 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.
|
||||||
|
@ -876,10 +876,17 @@ 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
|
# Setting these parameters makes it an error to link to macosx APIs that are
|
||||||
MACOSX_REQUIRED_VERSION=1070
|
# newer than the given OS version and makes the linked binaries compatible even
|
||||||
AC_SUBST(MACOSX_REQUIRED_VERSION)
|
# if built on a newer version of the OS.
|
||||||
CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(MACOSX_REQUIRED_VERSION) -DMAC_OS_X_VERSION_MIN_REQUIRED=\$(MACOSX_REQUIRED_VERSION)"
|
# The expected format is X.Y.Z
|
||||||
|
MACOSX_VERSION_MIN=10.7.0
|
||||||
|
AC_SUBST(MACOSX_VERSION_MIN)
|
||||||
|
# The macro takes the version with no dots, ex: 1070
|
||||||
|
# Let the flags variables get resolved in make for easier override on make
|
||||||
|
# command line.
|
||||||
|
CCXXFLAGS_JDK="$CCXXFLAGS_JDK -DMAC_OS_X_VERSION_MAX_ALLOWED=\$(subst .,,\$(MACOSX_VERSION_MIN)) -mmacosx-version-min=\$(MACOSX_VERSION_MIN)"
|
||||||
|
LDFLAGS_JDK="$LDFLAGS_JDK -mmacosx-version-min=\$(MACOSX_VERSION_MIN)"
|
||||||
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"
|
||||||
|
@ -501,7 +501,7 @@ define SetupJavaCompilation
|
|||||||
$(ECHO) Compiling $1
|
$(ECHO) Compiling $1
|
||||||
($$($1_JVM) $$($1_SJAVAC) \
|
($$($1_JVM) $$($1_SJAVAC) \
|
||||||
$$($1_REMOTE) \
|
$$($1_REMOTE) \
|
||||||
-j $(NUM_CORES) \
|
-j $(JOBS) \
|
||||||
--permit-unidentified-artifacts \
|
--permit-unidentified-artifacts \
|
||||||
--permit-sources-without-package \
|
--permit-sources-without-package \
|
||||||
--compare-found-sources $$($1_BIN)/_the.batch.tmp \
|
--compare-found-sources $$($1_BIN)/_the.batch.tmp \
|
||||||
|
@ -58,9 +58,6 @@ $(eval $(call ResetAllTimers))
|
|||||||
|
|
||||||
# Setup number of jobs to use. -jN is unfortunately not available for us to parse from the command line,
|
# Setup number of jobs to use. -jN is unfortunately not available for us to parse from the command line,
|
||||||
# hence this workaround.
|
# hence this workaround.
|
||||||
ifeq ($(JOBS),)
|
|
||||||
JOBS=$(NUM_CORES)
|
|
||||||
endif
|
|
||||||
MAKE_ARGS:=$(MAKE_ARGS) -j$(JOBS)
|
MAKE_ARGS:=$(MAKE_ARGS) -j$(JOBS)
|
||||||
|
|
||||||
### Main targets
|
### Main targets
|
||||||
|
@ -318,3 +318,5 @@ cdb46031e7184d37301288f5719121a63c7054b5 jdk8-b77
|
|||||||
9f19f4a7d48a4ebe7f616b6068971ea5f8b075fa hs25-b19
|
9f19f4a7d48a4ebe7f616b6068971ea5f8b075fa hs25-b19
|
||||||
d5e12e7d2f719144d84903d9151455661c47b476 jdk8-b78
|
d5e12e7d2f719144d84903d9151455661c47b476 jdk8-b78
|
||||||
555ec35a250783110aa070dbc8a8603f6cabe41f hs25-b20
|
555ec35a250783110aa070dbc8a8603f6cabe41f hs25-b20
|
||||||
|
6691814929b606fe0e7954fd6e485dd876505c83 jdk8-b79
|
||||||
|
df5396524152118535c36da5801d828b560d19a2 hs25-b21
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 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
|
# or visit www.oracle.com if you need additional information or have any
|
||||||
# questions.
|
# questions.
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
||||||
# This guards against adding broken .java files to the directory
|
# This guards against adding broken .java files to the directory
|
||||||
@ -42,8 +42,6 @@ PKGLIST = \
|
|||||||
sun.jvm.hotspot \
|
sun.jvm.hotspot \
|
||||||
sun.jvm.hotspot.asm \
|
sun.jvm.hotspot.asm \
|
||||||
sun.jvm.hotspot.asm.sparc \
|
sun.jvm.hotspot.asm.sparc \
|
||||||
sun.jvm.hotspot.bugspot \
|
|
||||||
sun.jvm.hotspot.bugspot.tree \
|
|
||||||
sun.jvm.hotspot.c1 \
|
sun.jvm.hotspot.c1 \
|
||||||
sun.jvm.hotspot.ci \
|
sun.jvm.hotspot.ci \
|
||||||
sun.jvm.hotspot.code \
|
sun.jvm.hotspot.code \
|
||||||
@ -84,7 +82,6 @@ sun.jvm.hotspot.gc_implementation.shared \
|
|||||||
sun.jvm.hotspot.gc_interface \
|
sun.jvm.hotspot.gc_interface \
|
||||||
sun.jvm.hotspot.interpreter \
|
sun.jvm.hotspot.interpreter \
|
||||||
sun.jvm.hotspot.jdi \
|
sun.jvm.hotspot.jdi \
|
||||||
sun.jvm.hotspot.livejvm \
|
|
||||||
sun.jvm.hotspot.memory \
|
sun.jvm.hotspot.memory \
|
||||||
sun.jvm.hotspot.opto \
|
sun.jvm.hotspot.opto \
|
||||||
sun.jvm.hotspot.oops \
|
sun.jvm.hotspot.oops \
|
||||||
@ -130,8 +127,6 @@ FILELIST = \
|
|||||||
sun/jvm/hotspot/*.java \
|
sun/jvm/hotspot/*.java \
|
||||||
sun/jvm/hotspot/asm/*.java \
|
sun/jvm/hotspot/asm/*.java \
|
||||||
sun/jvm/hotspot/asm/sparc/*.java \
|
sun/jvm/hotspot/asm/sparc/*.java \
|
||||||
sun/jvm/hotspot/bugspot/*.java \
|
|
||||||
sun/jvm/hotspot/bugspot/tree/*.java \
|
|
||||||
sun/jvm/hotspot/c1/*.java \
|
sun/jvm/hotspot/c1/*.java \
|
||||||
sun/jvm/hotspot/ci/*.java \
|
sun/jvm/hotspot/ci/*.java \
|
||||||
sun/jvm/hotspot/code/*.java \
|
sun/jvm/hotspot/code/*.java \
|
||||||
@ -168,7 +163,6 @@ sun/jvm/hotspot/gc_implementation/parallelScavenge/*.java \
|
|||||||
sun/jvm/hotspot/gc_implementation/shared/*.java \
|
sun/jvm/hotspot/gc_implementation/shared/*.java \
|
||||||
sun/jvm/hotspot/interpreter/*.java \
|
sun/jvm/hotspot/interpreter/*.java \
|
||||||
sun/jvm/hotspot/jdi/*.java \
|
sun/jvm/hotspot/jdi/*.java \
|
||||||
sun/jvm/hotspot/livejvm/*.java \
|
|
||||||
sun/jvm/hotspot/memory/*.java \
|
sun/jvm/hotspot/memory/*.java \
|
||||||
sun/jvm/hotspot/oops/*.java \
|
sun/jvm/hotspot/oops/*.java \
|
||||||
sun/jvm/hotspot/opto/*.java \
|
sun/jvm/hotspot/opto/*.java \
|
||||||
@ -205,7 +199,7 @@ sun/jvm/hotspot/utilities/*.java \
|
|||||||
sun/jvm/hotspot/utilities/memo/*.java \
|
sun/jvm/hotspot/utilities/memo/*.java \
|
||||||
sun/jvm/hotspot/utilities/soql/*.java \
|
sun/jvm/hotspot/utilities/soql/*.java \
|
||||||
com/sun/java/swing/action/*.java \
|
com/sun/java/swing/action/*.java \
|
||||||
com/sun/java/swing/ui/*.java
|
com/sun/java/swing/ui/*.java
|
||||||
#END FILELIST
|
#END FILELIST
|
||||||
|
|
||||||
ifneq "x$(ALT_BOOTDIR)" "x"
|
ifneq "x$(ALT_BOOTDIR)" "x"
|
||||||
@ -231,7 +225,7 @@ BUILD_DIR = ../build
|
|||||||
OUTPUT_DIR = $(BUILD_DIR)/classes
|
OUTPUT_DIR = $(BUILD_DIR)/classes
|
||||||
DOC_DIR = $(BUILD_DIR)/doc
|
DOC_DIR = $(BUILD_DIR)/doc
|
||||||
|
|
||||||
# gnumake 3.78.1 does not accept the *s,
|
# gnumake 3.78.1 does not accept the *s,
|
||||||
# so use the shell to expand them
|
# so use the shell to expand them
|
||||||
ALLFILES := $(patsubst %,$(SRC_DIR)/%,$(FILELIST))
|
ALLFILES := $(patsubst %,$(SRC_DIR)/%,$(FILELIST))
|
||||||
ALLFILES := $(shell /bin/ls $(ALLFILES))
|
ALLFILES := $(shell /bin/ls $(ALLFILES))
|
||||||
@ -303,7 +297,7 @@ sizes: $(ALLFILES)
|
|||||||
cscope: $(ALLFILES)
|
cscope: $(ALLFILES)
|
||||||
rm -f java.files
|
rm -f java.files
|
||||||
echo $(ALLFILES) > java.files
|
echo $(ALLFILES) > java.files
|
||||||
cscope -b -i java.files -f java.out
|
cscope -b -i java.files -f java.out
|
||||||
rm -f java.files
|
rm -f java.files
|
||||||
|
|
||||||
.PHONY: sa.jar
|
.PHONY: sa.jar
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
REM
|
|
||||||
REM Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
REM DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
REM
|
|
||||||
REM This code is free software; you can redistribute it and/or modify it
|
|
||||||
REM under the terms of the GNU General Public License version 2 only, as
|
|
||||||
REM published by the Free Software Foundation.
|
|
||||||
REM
|
|
||||||
REM This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
REM ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
REM FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
REM version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
REM accompanied this code).
|
|
||||||
REM
|
|
||||||
REM You should have received a copy of the GNU General Public License version
|
|
||||||
REM 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
REM Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
REM
|
|
||||||
REM Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
REM or visit www.oracle.com if you need additional information or have any
|
|
||||||
REM questions.
|
|
||||||
REM
|
|
||||||
REM
|
|
||||||
|
|
||||||
java -showversion -cp ..\build\classes;..\src\share\lib\js.jar;.\sa.jar;lib\js.jar sun.jvm.hotspot.bugspot.Main
|
|
@ -26,14 +26,12 @@
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><code>java -cp classes sun.jvm.hotspot.HSDB</code>
|
<li><code>java -cp classes sun.jvm.hotspot.HSDB</code>
|
||||||
<li><code>java -cp classes sun.jvm.hotspot.bugspot.Main</code>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<h2>Feedback</h2>
|
<h2>Feedback</h2>
|
||||||
<p>
|
<p>
|
||||||
Refactoring of package hierarchy. All user interface components should be in
|
Refactoring of package hierarchy. All user interface components should be in
|
||||||
the ui package. Perhaps: sun.jvm.hotspot.ui.hsdb.Main for the HSDB and
|
the ui package. Perhaps: sun.jvm.hotspot.ui.hsdb.Main for the HSDB.
|
||||||
sun.jvm.hotspot.ui.bugspot.Main for BugSpot.
|
|
||||||
<p>
|
<p>
|
||||||
The src\share\vm\agent area seems like a workspace so it should be organized like
|
The src\share\vm\agent area seems like a workspace so it should be organized like
|
||||||
one. In particular, I'd like to suggest the following directory layout:<br>
|
one. In particular, I'd like to suggest the following directory layout:<br>
|
||||||
@ -47,7 +45,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Seems like there is a lot of redundant functionality. Between the HSDB and BugSpot. Perhaps
|
Seems like there is a lot of redundant functionality. Perhaps
|
||||||
this can be consolidated with a <code>javax.swing.Actions</code> architecture.
|
this can be consolidated with a <code>javax.swing.Actions</code> architecture.
|
||||||
|
|
||||||
<h2>Tasklist</h2>
|
<h2>Tasklist</h2>
|
||||||
@ -55,11 +53,7 @@
|
|||||||
<p>
|
<p>
|
||||||
<b>Stack memory pane</b>:
|
<b>Stack memory pane</b>:
|
||||||
It's one of the more useful JVM debugging tools in the SA. However, it
|
It's one of the more useful JVM debugging tools in the SA. However, it
|
||||||
doesn't support any interaction with the text; the Memory Panel in BugSpot
|
doesn't support any interaction with the text.
|
||||||
was written afterward (with help from Shannon) and implements proper
|
|
||||||
selection, scrolling, and drag-and-drop, but no annotations. I'm not sure how
|
|
||||||
to integrate the annotations with the JTable that's being used for the memory
|
|
||||||
view; if you have suggestions here please let me know.
|
|
||||||
<p>
|
<p>
|
||||||
<b>Integrations with the NetBeans architecture (plug in).</b> See the
|
<b>Integrations with the NetBeans architecture (plug in).</b> See the
|
||||||
<a href="http://openide.netbeans.org">Netbeans Open APIs homepage</a>
|
<a href="http://openide.netbeans.org">Netbeans Open APIs homepage</a>
|
||||||
|
@ -372,8 +372,7 @@ static bool attachToProcess(JNIEnv* env, jobject obj, jint pid) {
|
|||||||
|
|
||||||
We are attaching to a process in 'read-only' mode. i.e., we do not want to
|
We are attaching to a process in 'read-only' mode. i.e., we do not want to
|
||||||
put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of
|
put breakpoints, suspend/resume threads etc. For read-only JDI and HSDB kind of
|
||||||
usage this should suffice. We are not intending to use this for full-fledged
|
usage this should suffice.
|
||||||
ProcessControl implementation to be used with BugSpotAgent.
|
|
||||||
|
|
||||||
Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
|
Please refer to DEBUG_ATTACH_NONINVASIVE mode source comments from dbgeng.h.
|
||||||
In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
|
In this mode, debug engine does not call DebugActiveProrcess. i.e., we are not
|
||||||
|
@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.asm.amd64;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.asm.Register;
|
|
||||||
import sun.jvm.hotspot.utilities.Assert;
|
|
||||||
|
|
||||||
public class AMD64FloatRegister extends Register {
|
|
||||||
|
|
||||||
public AMD64FloatRegister(int number) {
|
|
||||||
super(number);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumber() {
|
|
||||||
return number;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumberOfRegisters() {
|
|
||||||
return AMD64FloatRegisters.getNumRegisters();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFloat() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isFramePointer() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isStackPointer() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isValid() {
|
|
||||||
return number >= 0 && number < AMD64FloatRegisters.getNumRegisters();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
return AMD64FloatRegisters.getRegisterName(number);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
@ -1,799 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import java.io.PrintStream;
|
|
||||||
import java.net.*;
|
|
||||||
import java.rmi.*;
|
|
||||||
import sun.jvm.hotspot.*;
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.debugger.bsd.*;
|
|
||||||
import sun.jvm.hotspot.debugger.proc.*;
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.debugger.windbg.*;
|
|
||||||
import sun.jvm.hotspot.debugger.linux.*;
|
|
||||||
import sun.jvm.hotspot.debugger.sparc.*;
|
|
||||||
import sun.jvm.hotspot.debugger.remote.*;
|
|
||||||
import sun.jvm.hotspot.livejvm.*;
|
|
||||||
import sun.jvm.hotspot.memory.*;
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
import sun.jvm.hotspot.types.*;
|
|
||||||
import sun.jvm.hotspot.utilities.*;
|
|
||||||
|
|
||||||
/** <P> This class wraps the basic functionality for connecting to the
|
|
||||||
* target process or debug server. It makes it simple to start up the
|
|
||||||
* debugging system. </P>
|
|
||||||
*
|
|
||||||
* <P> This agent (as compared to the HotSpotAgent) can connect to
|
|
||||||
* and interact with arbitrary processes. If the target process
|
|
||||||
* happens to be a HotSpot JVM, the Java debugging features of the
|
|
||||||
* Serviceability Agent are enabled. Further, if the Serviceability
|
|
||||||
* Agent's JVMDI module is loaded into the target VM, interaction
|
|
||||||
* with the live Java program is possible, specifically the catching
|
|
||||||
* of exceptions and setting of breakpoints. </P>
|
|
||||||
*
|
|
||||||
* <P> The BugSpot debugger requires that the underlying Debugger
|
|
||||||
* support C/C++ debugging via the CDebugger interface. </P>
|
|
||||||
*
|
|
||||||
* <P> FIXME: especially with the addition of remote debugging, this
|
|
||||||
* has turned into a mess; needs rethinking. </P> */
|
|
||||||
|
|
||||||
public class BugSpotAgent {
|
|
||||||
|
|
||||||
private JVMDebugger debugger;
|
|
||||||
private MachineDescription machDesc;
|
|
||||||
private TypeDataBase db;
|
|
||||||
|
|
||||||
private String os;
|
|
||||||
private String cpu;
|
|
||||||
private String fileSep;
|
|
||||||
|
|
||||||
// The system can work in several ways:
|
|
||||||
// - Attaching to local process
|
|
||||||
// - Attaching to local core file
|
|
||||||
// - Connecting to remote debug server
|
|
||||||
// - Starting debug server for process
|
|
||||||
// - Starting debug server for core file
|
|
||||||
|
|
||||||
// These are options for the "client" side of things
|
|
||||||
private static final int PROCESS_MODE = 0;
|
|
||||||
private static final int CORE_FILE_MODE = 1;
|
|
||||||
private static final int REMOTE_MODE = 2;
|
|
||||||
private int startupMode;
|
|
||||||
|
|
||||||
// This indicates whether we are really starting a server or not
|
|
||||||
private boolean isServer;
|
|
||||||
|
|
||||||
// All possible required information for connecting
|
|
||||||
private int pid;
|
|
||||||
private String executableName;
|
|
||||||
private String coreFileName;
|
|
||||||
private String debugServerID;
|
|
||||||
|
|
||||||
// All needed information for server side
|
|
||||||
private String serverID;
|
|
||||||
|
|
||||||
// Indicates whether we are attached to a HotSpot JVM or not
|
|
||||||
private boolean javaMode;
|
|
||||||
|
|
||||||
// Indicates whether we have process control over a live HotSpot JVM
|
|
||||||
// or not; non-null if so.
|
|
||||||
private ServiceabilityAgentJVMDIModule jvmdi;
|
|
||||||
// While handling C breakpoints interactivity with the Java program
|
|
||||||
// is forbidden. Too many invariants are broken while the target is
|
|
||||||
// stopped at a C breakpoint to risk making JVMDI calls.
|
|
||||||
private boolean javaInteractionDisabled;
|
|
||||||
|
|
||||||
private String[] jvmLibNames;
|
|
||||||
private String[] saLibNames;
|
|
||||||
|
|
||||||
// FIXME: make these configurable, i.e., via a dotfile; also
|
|
||||||
// consider searching within the JDK from which this Java executable
|
|
||||||
// comes to find them
|
|
||||||
private static final String defaultDbxPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa";
|
|
||||||
private static final String defaultDbxSvcAgentDSOPathPrefix = "/net/jano.eng/export/disk05/hotspot/sa";
|
|
||||||
|
|
||||||
private static final boolean DEBUG;
|
|
||||||
static {
|
|
||||||
DEBUG = System.getProperty("sun.jvm.hotspot.bugspot.BugSpotAgent.DEBUG")
|
|
||||||
!= null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void debugPrintln(String str) {
|
|
||||||
if (DEBUG) {
|
|
||||||
System.err.println(str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void showUsage() {
|
|
||||||
System.out.println(" You can also pass these -D options to java to specify where to find dbx and the \n" +
|
|
||||||
" Serviceability Agent plugin for dbx:");
|
|
||||||
System.out.println(" -DdbxPathName=<path-to-dbx-executable>\n" +
|
|
||||||
" Default is derived from dbxPathPrefix");
|
|
||||||
System.out.println(" or");
|
|
||||||
System.out.println(" -DdbxPathPrefix=<xxx>\n" +
|
|
||||||
" where xxx is the path name of a dir structure that contains:\n" +
|
|
||||||
" <os>/<arch>/bin/dbx\n" +
|
|
||||||
" The default is " + defaultDbxPathPrefix);
|
|
||||||
System.out.println(" and");
|
|
||||||
System.out.println(" -DdbxSvcAgentDSOPathName=<path-to-dbx-serviceability-agent-module>\n" +
|
|
||||||
" Default is determined from dbxSvcAgentDSOPathPrefix");
|
|
||||||
System.out.println(" or");
|
|
||||||
System.out.println(" -DdbxSvcAgentDSOPathPrefix=<xxx>\n" +
|
|
||||||
" where xxx is the pathname of a dir structure that contains:\n" +
|
|
||||||
" <os>/<arch>/bin/lib/libsvc_agent_dbx.so\n" +
|
|
||||||
" The default is " + defaultDbxSvcAgentDSOPathPrefix);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BugSpotAgent() {
|
|
||||||
// for non-server add shutdown hook to clean-up debugger in case
|
|
||||||
// of forced exit. For remote server, shutdown hook is added by
|
|
||||||
// DebugServer.
|
|
||||||
Runtime.getRuntime().addShutdownHook(new java.lang.Thread(
|
|
||||||
new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
synchronized (BugSpotAgent.this) {
|
|
||||||
if (!isServer) {
|
|
||||||
detach();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
// Accessors (once the system is set up)
|
|
||||||
//
|
|
||||||
|
|
||||||
public synchronized Debugger getDebugger() {
|
|
||||||
return debugger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized CDebugger getCDebugger() {
|
|
||||||
return getDebugger().getCDebugger();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized ProcessControl getProcessControl() {
|
|
||||||
return getCDebugger().getProcessControl();
|
|
||||||
}
|
|
||||||
|
|
||||||
public synchronized TypeDataBase getTypeDataBase() {
|
|
||||||
return db;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether the target process is suspended
|
|
||||||
completely. Equivalent to getProcessControl().isSuspended(). */
|
|
||||||
public synchronized boolean isSuspended() throws DebuggerException {
|
|
||||||
return getProcessControl().isSuspended();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Suspends the target process completely. Equivalent to
|
|
||||||
getProcessControl().suspend(). */
|
|
||||||
public synchronized void suspend() throws DebuggerException {
|
|
||||||
getProcessControl().suspend();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Resumes the target process completely. Equivalent to
|
|
||||||
getProcessControl().suspend(). */
|
|
||||||
public synchronized void resume() throws DebuggerException {
|
|
||||||
getProcessControl().resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether we are attached to a Java HotSpot virtual
|
|
||||||
machine */
|
|
||||||
public synchronized boolean isJavaMode() {
|
|
||||||
return javaMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Temporarily disables interaction with the target process via
|
|
||||||
JVMDI. This is done while the target process is stopped at a C
|
|
||||||
breakpoint. Can be called even if the JVMDI agent has not been
|
|
||||||
initialized. */
|
|
||||||
public synchronized void disableJavaInteraction() {
|
|
||||||
javaInteractionDisabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Re-enables interaction with the target process via JVMDI. This
|
|
||||||
is done while the target process is continued past a C
|
|
||||||
braekpoint. Can be called even if the JVMDI agent has not been
|
|
||||||
initialized. */
|
|
||||||
public synchronized void enableJavaInteraction() {
|
|
||||||
javaInteractionDisabled = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether Java interaction has been disabled */
|
|
||||||
public synchronized boolean isJavaInteractionDisabled() {
|
|
||||||
return javaInteractionDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether we can talk to the Serviceability Agent's
|
|
||||||
JVMDI module to be able to set breakpoints */
|
|
||||||
public synchronized boolean canInteractWithJava() {
|
|
||||||
return (jvmdi != null) && !javaInteractionDisabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Suspends all Java threads in the target process. Can only be
|
|
||||||
called if we are attached to a HotSpot JVM and can connect to
|
|
||||||
the SA's JVMDI module. Must not be called when the target
|
|
||||||
process has been suspended with suspend(). */
|
|
||||||
public synchronized void suspendJava() throws DebuggerException {
|
|
||||||
if (!canInteractWithJava()) {
|
|
||||||
throw new DebuggerException("Could not connect to SA's JVMDI module");
|
|
||||||
}
|
|
||||||
if (jvmdi.isSuspended()) {
|
|
||||||
throw new DebuggerException("Target process already suspended via JVMDI");
|
|
||||||
}
|
|
||||||
jvmdi.suspend();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Resumes all Java threads in the target process. Can only be
|
|
||||||
called if we are attached to a HotSpot JVM and can connect to
|
|
||||||
the SA's JVMDI module. Must not be called when the target
|
|
||||||
process has been suspended with suspend(). */
|
|
||||||
public synchronized void resumeJava() throws DebuggerException {
|
|
||||||
if (!canInteractWithJava()) {
|
|
||||||
throw new DebuggerException("Could not connect to SA's JVMDI module");
|
|
||||||
}
|
|
||||||
if (!jvmdi.isSuspended()) {
|
|
||||||
throw new DebuggerException("Target process already resumed via JVMDI");
|
|
||||||
}
|
|
||||||
jvmdi.resume();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether the target process has been suspended at the
|
|
||||||
Java language level via the SA's JVMDI module */
|
|
||||||
public synchronized boolean isJavaSuspended() throws DebuggerException {
|
|
||||||
return jvmdi.isSuspended();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Toggle a Java breakpoint at the given location. */
|
|
||||||
public synchronized ServiceabilityAgentJVMDIModule.BreakpointToggleResult
|
|
||||||
toggleJavaBreakpoint(String srcFileName,
|
|
||||||
String pkgName,
|
|
||||||
int lineNo) {
|
|
||||||
if (!canInteractWithJava()) {
|
|
||||||
throw new DebuggerException("Could not connect to SA's JVMDI module; can not toggle Java breakpoints");
|
|
||||||
}
|
|
||||||
return jvmdi.toggleBreakpoint(srcFileName, pkgName, lineNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Access to JVMDI module's eventPending */
|
|
||||||
public synchronized boolean javaEventPending() throws DebuggerException {
|
|
||||||
if (!canInteractWithJava()) {
|
|
||||||
throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events");
|
|
||||||
}
|
|
||||||
return jvmdi.eventPending();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Access to JVMDI module's eventPoll */
|
|
||||||
public synchronized Event javaEventPoll() throws DebuggerException {
|
|
||||||
if (!canInteractWithJava()) {
|
|
||||||
throw new DebuggerException("Could not connect to SA's JVMDI module; can not poll for Java debug events");
|
|
||||||
}
|
|
||||||
return jvmdi.eventPoll();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Access to JVMDI module's eventContinue */
|
|
||||||
public synchronized void javaEventContinue() throws DebuggerException {
|
|
||||||
if (!canInteractWithJava()) {
|
|
||||||
throw new DebuggerException("Could not connect to SA's JVMDI module; can not continue past Java debug events");
|
|
||||||
}
|
|
||||||
jvmdi.eventContinue();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// FIXME: add other accessors. For example, suspension and
|
|
||||||
// resumption should be done through this interface, as well as
|
|
||||||
// interaction with the live Java process such as breakpoint setting.
|
|
||||||
// Probably should not expose the ServiceabilityAgentJVMDIModule
|
|
||||||
// from this interface.
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
// Client-side operations
|
|
||||||
//
|
|
||||||
|
|
||||||
/** This attaches to a process running on the local machine. */
|
|
||||||
public synchronized void attach(int processID)
|
|
||||||
throws DebuggerException {
|
|
||||||
if (debugger != null) {
|
|
||||||
throw new DebuggerException("Already attached");
|
|
||||||
}
|
|
||||||
pid = processID;
|
|
||||||
startupMode = PROCESS_MODE;
|
|
||||||
isServer = false;
|
|
||||||
go();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This opens a core file on the local machine */
|
|
||||||
public synchronized void attach(String executableName, String coreFileName)
|
|
||||||
throws DebuggerException {
|
|
||||||
if (debugger != null) {
|
|
||||||
throw new DebuggerException("Already attached");
|
|
||||||
}
|
|
||||||
if ((executableName == null) || (coreFileName == null)) {
|
|
||||||
throw new DebuggerException("Both the core file name and executable name must be specified");
|
|
||||||
}
|
|
||||||
this.executableName = executableName;
|
|
||||||
this.coreFileName = coreFileName;
|
|
||||||
startupMode = CORE_FILE_MODE;
|
|
||||||
isServer = false;
|
|
||||||
go();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This attaches to a "debug server" on a remote machine; this
|
|
||||||
remote server has already attached to a process or opened a
|
|
||||||
core file and is waiting for RMI calls on the Debugger object to
|
|
||||||
come in. */
|
|
||||||
public synchronized void attach(String remoteServerID)
|
|
||||||
throws DebuggerException {
|
|
||||||
if (debugger != null) {
|
|
||||||
throw new DebuggerException("Already attached to a process");
|
|
||||||
}
|
|
||||||
if (remoteServerID == null) {
|
|
||||||
throw new DebuggerException("Debug server id must be specified");
|
|
||||||
}
|
|
||||||
|
|
||||||
debugServerID = remoteServerID;
|
|
||||||
startupMode = REMOTE_MODE;
|
|
||||||
isServer = false;
|
|
||||||
go();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This should only be called by the user on the client machine,
|
|
||||||
not the server machine */
|
|
||||||
public synchronized boolean detach() throws DebuggerException {
|
|
||||||
if (isServer) {
|
|
||||||
throw new DebuggerException("Should not call detach() for server configuration");
|
|
||||||
}
|
|
||||||
return detachInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
// Server-side operations
|
|
||||||
//
|
|
||||||
|
|
||||||
/** This attaches to a process running on the local machine and
|
|
||||||
starts a debug server, allowing remote machines to connect and
|
|
||||||
examine this process. uniqueID is used to uniquely identify the
|
|
||||||
debuggee */
|
|
||||||
public synchronized void startServer(int processID, String uniqueID)
|
|
||||||
throws DebuggerException {
|
|
||||||
if (debugger != null) {
|
|
||||||
throw new DebuggerException("Already attached");
|
|
||||||
}
|
|
||||||
pid = processID;
|
|
||||||
startupMode = PROCESS_MODE;
|
|
||||||
isServer = true;
|
|
||||||
serverID = uniqueID;
|
|
||||||
go();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This attaches to a process running on the local machine and
|
|
||||||
starts a debug server, allowing remote machines to connect and
|
|
||||||
examine this process. */
|
|
||||||
public synchronized void startServer(int processID)
|
|
||||||
throws DebuggerException {
|
|
||||||
startServer(processID, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This opens a core file on the local machine and starts a debug
|
|
||||||
server, allowing remote machines to connect and examine this
|
|
||||||
core file. uniqueID is used to uniquely identify the
|
|
||||||
debuggee */
|
|
||||||
public synchronized void startServer(String executableName, String coreFileName,
|
|
||||||
String uniqueID)
|
|
||||||
throws DebuggerException {
|
|
||||||
if (debugger != null) {
|
|
||||||
throw new DebuggerException("Already attached");
|
|
||||||
}
|
|
||||||
if ((executableName == null) || (coreFileName == null)) {
|
|
||||||
throw new DebuggerException("Both the core file name and Java executable name must be specified");
|
|
||||||
}
|
|
||||||
this.executableName = executableName;
|
|
||||||
this.coreFileName = coreFileName;
|
|
||||||
startupMode = CORE_FILE_MODE;
|
|
||||||
isServer = true;
|
|
||||||
serverID = uniqueID;
|
|
||||||
go();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This opens a core file on the local machine and starts a debug
|
|
||||||
server, allowing remote machines to connect and examine this
|
|
||||||
core file.*/
|
|
||||||
public synchronized void startServer(String executableName, String coreFileName)
|
|
||||||
throws DebuggerException {
|
|
||||||
startServer(executableName, coreFileName, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** This may only be called on the server side after startServer()
|
|
||||||
has been called */
|
|
||||||
public synchronized boolean shutdownServer() throws DebuggerException {
|
|
||||||
if (!isServer) {
|
|
||||||
throw new DebuggerException("Should not call shutdownServer() for client configuration");
|
|
||||||
}
|
|
||||||
return detachInternal();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
// Internals only below this point
|
|
||||||
//
|
|
||||||
|
|
||||||
private boolean detachInternal() {
|
|
||||||
if (debugger == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (canInteractWithJava()) {
|
|
||||||
jvmdi.detach();
|
|
||||||
jvmdi = null;
|
|
||||||
}
|
|
||||||
boolean retval = true;
|
|
||||||
if (!isServer) {
|
|
||||||
VM.shutdown();
|
|
||||||
}
|
|
||||||
// We must not call detach() if we are a client and are connected
|
|
||||||
// to a remote debugger
|
|
||||||
Debugger dbg = null;
|
|
||||||
DebuggerException ex = null;
|
|
||||||
if (isServer) {
|
|
||||||
try {
|
|
||||||
RMIHelper.unbind(serverID);
|
|
||||||
}
|
|
||||||
catch (DebuggerException de) {
|
|
||||||
ex = de;
|
|
||||||
}
|
|
||||||
dbg = debugger;
|
|
||||||
} else {
|
|
||||||
if (startupMode != REMOTE_MODE) {
|
|
||||||
dbg = debugger;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (dbg != null) {
|
|
||||||
retval = dbg.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
debugger = null;
|
|
||||||
machDesc = null;
|
|
||||||
db = null;
|
|
||||||
if (ex != null) {
|
|
||||||
throw(ex);
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void go() {
|
|
||||||
setupDebugger();
|
|
||||||
javaMode = setupVM();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupDebugger() {
|
|
||||||
if (startupMode != REMOTE_MODE) {
|
|
||||||
//
|
|
||||||
// Local mode (client attaching to local process or setting up
|
|
||||||
// server, but not client attaching to server)
|
|
||||||
//
|
|
||||||
|
|
||||||
try {
|
|
||||||
os = PlatformInfo.getOS();
|
|
||||||
cpu = PlatformInfo.getCPU();
|
|
||||||
}
|
|
||||||
catch (UnsupportedPlatformException e) {
|
|
||||||
throw new DebuggerException(e);
|
|
||||||
}
|
|
||||||
fileSep = System.getProperty("file.separator");
|
|
||||||
|
|
||||||
if (os.equals("solaris")) {
|
|
||||||
setupDebuggerSolaris();
|
|
||||||
} else if (os.equals("win32")) {
|
|
||||||
setupDebuggerWin32();
|
|
||||||
} else if (os.equals("linux")) {
|
|
||||||
setupDebuggerLinux();
|
|
||||||
} else if (os.equals("bsd")) {
|
|
||||||
setupDebuggerBsd();
|
|
||||||
} else {
|
|
||||||
// Add support for more operating systems here
|
|
||||||
throw new DebuggerException("Operating system " + os + " not yet supported");
|
|
||||||
}
|
|
||||||
if (isServer) {
|
|
||||||
RemoteDebuggerServer remote = null;
|
|
||||||
try {
|
|
||||||
remote = new RemoteDebuggerServer(debugger);
|
|
||||||
}
|
|
||||||
catch (RemoteException rem) {
|
|
||||||
throw new DebuggerException(rem);
|
|
||||||
}
|
|
||||||
RMIHelper.rebind(serverID, remote);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//
|
|
||||||
// Remote mode (client attaching to server)
|
|
||||||
//
|
|
||||||
|
|
||||||
// Create and install a security manager
|
|
||||||
|
|
||||||
// FIXME: currently commented out because we were having
|
|
||||||
// security problems since we're "in the sun.* hierarchy" here.
|
|
||||||
// Perhaps a permissive policy file would work around this. In
|
|
||||||
// the long run, will probably have to move into com.sun.*.
|
|
||||||
|
|
||||||
// if (System.getSecurityManager() == null) {
|
|
||||||
// System.setSecurityManager(new RMISecurityManager());
|
|
||||||
// }
|
|
||||||
|
|
||||||
connectRemoteDebugger();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean setupVM() {
|
|
||||||
// We need to instantiate a HotSpotTypeDataBase on both the client
|
|
||||||
// and server machine. On the server it is only currently used to
|
|
||||||
// configure the Java primitive type sizes (which we should
|
|
||||||
// consider making constant). On the client it is used to
|
|
||||||
// configure the VM.
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (os.equals("solaris")) {
|
|
||||||
db = new HotSpotTypeDataBase(machDesc, new HotSpotSolarisVtblAccess(debugger, jvmLibNames),
|
|
||||||
debugger, jvmLibNames);
|
|
||||||
} else if (os.equals("win32")) {
|
|
||||||
db = new HotSpotTypeDataBase(machDesc, new Win32VtblAccess(debugger, jvmLibNames),
|
|
||||||
debugger, jvmLibNames);
|
|
||||||
} else if (os.equals("linux")) {
|
|
||||||
db = new HotSpotTypeDataBase(machDesc, new LinuxVtblAccess(debugger, jvmLibNames),
|
|
||||||
debugger, jvmLibNames);
|
|
||||||
} else if (os.equals("bsd")) {
|
|
||||||
db = new HotSpotTypeDataBase(machDesc, new BsdVtblAccess(debugger, jvmLibNames),
|
|
||||||
debugger, jvmLibNames);
|
|
||||||
} else {
|
|
||||||
throw new DebuggerException("OS \"" + os + "\" not yet supported (no VtblAccess implemented yet)");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (NoSuchSymbolException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (startupMode != REMOTE_MODE) {
|
|
||||||
// Configure the debugger with the primitive type sizes just obtained from the VM
|
|
||||||
debugger.configureJavaPrimitiveTypeSizes(db.getJBooleanType().getSize(),
|
|
||||||
db.getJByteType().getSize(),
|
|
||||||
db.getJCharType().getSize(),
|
|
||||||
db.getJDoubleType().getSize(),
|
|
||||||
db.getJFloatType().getSize(),
|
|
||||||
db.getJIntType().getSize(),
|
|
||||||
db.getJLongType().getSize(),
|
|
||||||
db.getJShortType().getSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isServer) {
|
|
||||||
// Do not initialize the VM on the server (unnecessary, since it's
|
|
||||||
// instantiated on the client)
|
|
||||||
VM.initialize(db, debugger);
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
jvmdi = new ServiceabilityAgentJVMDIModule(debugger, saLibNames);
|
|
||||||
if (jvmdi.canAttach()) {
|
|
||||||
jvmdi.attach();
|
|
||||||
jvmdi.setCommandTimeout(6000);
|
|
||||||
debugPrintln("Attached to Serviceability Agent's JVMDI module.");
|
|
||||||
// Jog VM to suspended point with JVMDI module
|
|
||||||
resume();
|
|
||||||
suspendJava();
|
|
||||||
suspend();
|
|
||||||
debugPrintln("Suspended all Java threads.");
|
|
||||||
} else {
|
|
||||||
debugPrintln("Could not locate SA's JVMDI module; skipping attachment");
|
|
||||||
jvmdi = null;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
jvmdi = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
|
||||||
// OS-specific debugger setup/connect routines
|
|
||||||
//
|
|
||||||
|
|
||||||
//
|
|
||||||
// Solaris
|
|
||||||
//
|
|
||||||
|
|
||||||
private void setupDebuggerSolaris() {
|
|
||||||
setupJVMLibNamesSolaris();
|
|
||||||
ProcDebuggerLocal dbg = new ProcDebuggerLocal(null, true);
|
|
||||||
debugger = dbg;
|
|
||||||
attachDebugger();
|
|
||||||
|
|
||||||
// Set up CPU-dependent stuff
|
|
||||||
if (cpu.equals("x86")) {
|
|
||||||
machDesc = new MachineDescriptionIntelX86();
|
|
||||||
} else if (cpu.equals("sparc")) {
|
|
||||||
int addressSize = dbg.getRemoteProcessAddressSize();
|
|
||||||
if (addressSize == -1) {
|
|
||||||
throw new DebuggerException("Error occurred while trying to determine the remote process's address size");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addressSize == 32) {
|
|
||||||
machDesc = new MachineDescriptionSPARC32Bit();
|
|
||||||
} else if (addressSize == 64) {
|
|
||||||
machDesc = new MachineDescriptionSPARC64Bit();
|
|
||||||
} else {
|
|
||||||
throw new DebuggerException("Address size " + addressSize + " is not supported on SPARC");
|
|
||||||
}
|
|
||||||
} else if (cpu.equals("amd64")) {
|
|
||||||
machDesc = new MachineDescriptionAMD64();
|
|
||||||
} else {
|
|
||||||
throw new DebuggerException("Solaris only supported on sparc/sparcv9/x86/amd64");
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg.setMachineDescription(machDesc);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void connectRemoteDebugger() throws DebuggerException {
|
|
||||||
RemoteDebugger remote =
|
|
||||||
(RemoteDebugger) RMIHelper.lookup(debugServerID);
|
|
||||||
debugger = new RemoteDebuggerClient(remote);
|
|
||||||
machDesc = ((RemoteDebuggerClient) debugger).getMachineDescription();
|
|
||||||
os = debugger.getOS();
|
|
||||||
if (os.equals("solaris")) {
|
|
||||||
setupJVMLibNamesSolaris();
|
|
||||||
} else if (os.equals("win32")) {
|
|
||||||
setupJVMLibNamesWin32();
|
|
||||||
} else if (os.equals("linux")) {
|
|
||||||
setupJVMLibNamesLinux();
|
|
||||||
} else if (os.equals("bsd")) {
|
|
||||||
setupJVMLibNamesBsd();
|
|
||||||
} else {
|
|
||||||
throw new RuntimeException("Unknown OS type");
|
|
||||||
}
|
|
||||||
|
|
||||||
cpu = debugger.getCPU();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupJVMLibNamesSolaris() {
|
|
||||||
jvmLibNames = new String[] { "libjvm.so", "libjvm_g.so", "gamma_g" };
|
|
||||||
saLibNames = new String[] { "libsa.so", "libsa_g.so" };
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Win32
|
|
||||||
//
|
|
||||||
|
|
||||||
private void setupDebuggerWin32() {
|
|
||||||
setupJVMLibNamesWin32();
|
|
||||||
|
|
||||||
if (cpu.equals("x86")) {
|
|
||||||
machDesc = new MachineDescriptionIntelX86();
|
|
||||||
} else if (cpu.equals("amd64")) {
|
|
||||||
machDesc = new MachineDescriptionAMD64();
|
|
||||||
} else if (cpu.equals("ia64")) {
|
|
||||||
machDesc = new MachineDescriptionIA64();
|
|
||||||
} else {
|
|
||||||
throw new DebuggerException("Win32 supported under x86, amd64 and ia64 only");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note we do not use a cache for the local debugger in server
|
|
||||||
// mode; it will be taken care of on the client side (once remote
|
|
||||||
// debugging is implemented).
|
|
||||||
|
|
||||||
debugger = new WindbgDebuggerLocal(machDesc, !isServer);
|
|
||||||
|
|
||||||
attachDebugger();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupJVMLibNamesWin32() {
|
|
||||||
jvmLibNames = new String[] { "jvm.dll", "jvm_g.dll" };
|
|
||||||
saLibNames = new String[] { "sa.dll", "sa_g.dll" };
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Linux
|
|
||||||
//
|
|
||||||
|
|
||||||
private void setupDebuggerLinux() {
|
|
||||||
setupJVMLibNamesLinux();
|
|
||||||
|
|
||||||
if (cpu.equals("x86")) {
|
|
||||||
machDesc = new MachineDescriptionIntelX86();
|
|
||||||
} else if (cpu.equals("ia64")) {
|
|
||||||
machDesc = new MachineDescriptionIA64();
|
|
||||||
} else if (cpu.equals("amd64")) {
|
|
||||||
machDesc = new MachineDescriptionAMD64();
|
|
||||||
} else if (cpu.equals("sparc")) {
|
|
||||||
if (LinuxDebuggerLocal.getAddressSize()==8) {
|
|
||||||
machDesc = new MachineDescriptionSPARC64Bit();
|
|
||||||
} else {
|
|
||||||
machDesc = new MachineDescriptionSPARC32Bit();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
machDesc = (MachineDescription)
|
|
||||||
Class.forName("sun.jvm.hotspot.debugger.MachineDescription" +
|
|
||||||
cpu.toUpperCase()).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new DebuggerException("unsupported machine type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Note we do not use a cache for the local debugger in server
|
|
||||||
// mode; it will be taken care of on the client side (once remote
|
|
||||||
// debugging is implemented).
|
|
||||||
|
|
||||||
debugger = new LinuxDebuggerLocal(machDesc, !isServer);
|
|
||||||
attachDebugger();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupJVMLibNamesLinux() {
|
|
||||||
// same as solaris
|
|
||||||
setupJVMLibNamesSolaris();
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// BSD
|
|
||||||
//
|
|
||||||
|
|
||||||
private void setupDebuggerBsd() {
|
|
||||||
setupJVMLibNamesBsd();
|
|
||||||
|
|
||||||
if (cpu.equals("x86")) {
|
|
||||||
machDesc = new MachineDescriptionIntelX86();
|
|
||||||
} else if (cpu.equals("amd64") || (cpu.equals("x86_64"))) {
|
|
||||||
machDesc = new MachineDescriptionAMD64();
|
|
||||||
} else {
|
|
||||||
throw new DebuggerException("Bsd only supported on x86/x86_64. Current arch: " + cpu);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note we do not use a cache for the local debugger in server
|
|
||||||
// mode; it will be taken care of on the client side (once remote
|
|
||||||
// debugging is implemented).
|
|
||||||
|
|
||||||
debugger = new BsdDebuggerLocal(machDesc, !isServer);
|
|
||||||
attachDebugger();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupJVMLibNamesBsd() {
|
|
||||||
// same as solaris
|
|
||||||
setupJVMLibNamesSolaris();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Convenience routine which should be called by per-platform
|
|
||||||
debugger setup. Should not be called when startupMode is
|
|
||||||
REMOTE_MODE. */
|
|
||||||
private void attachDebugger() {
|
|
||||||
if (startupMode == PROCESS_MODE) {
|
|
||||||
debugger.attach(pid);
|
|
||||||
} else if (startupMode == CORE_FILE_MODE) {
|
|
||||||
debugger.attach(executableName, coreFileName);
|
|
||||||
} else {
|
|
||||||
throw new DebuggerException("Should not call attach() for startupMode == " + startupMode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
|
|
||||||
/** Wrapper class which describes line number information for Java
|
|
||||||
class files. The line number table is converted into this
|
|
||||||
representation on demand. These objects are then sorted by line
|
|
||||||
number for fast lookup when setting breakpoints in a particular
|
|
||||||
source file. */
|
|
||||||
|
|
||||||
public class JavaLineNumberInfo {
|
|
||||||
private InstanceKlass klass;
|
|
||||||
private Method method;
|
|
||||||
private int startBCI;
|
|
||||||
private int lineNumber;
|
|
||||||
|
|
||||||
public JavaLineNumberInfo(InstanceKlass klass,
|
|
||||||
Method method,
|
|
||||||
int startBCI,
|
|
||||||
int lineNumber) {
|
|
||||||
this.klass = klass;
|
|
||||||
this.method = method;
|
|
||||||
this.startBCI = startBCI;
|
|
||||||
this.lineNumber = lineNumber;
|
|
||||||
}
|
|
||||||
|
|
||||||
public InstanceKlass getKlass() { return klass; }
|
|
||||||
public Method getMethod() { return method; }
|
|
||||||
public int getStartBCI() { return startBCI; }
|
|
||||||
public int getLineNumber() { return lineNumber; }
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.*;
|
|
||||||
import javax.swing.*;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.ui.*;
|
|
||||||
|
|
||||||
/** The main class for the BugSpot debugger. */
|
|
||||||
|
|
||||||
public class Main {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
JFrame frame = new JFrame("BugSpot");
|
|
||||||
frame.setSize(800, 600);
|
|
||||||
BugSpot db = new BugSpot();
|
|
||||||
db.setMDIMode(true);
|
|
||||||
db.build();
|
|
||||||
frame.setJMenuBar(db.getMenuBar());
|
|
||||||
frame.getContentPane().add(db);
|
|
||||||
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
|
|
||||||
|
|
||||||
GraphicsUtilities.reshapeToAspectRatio(frame,
|
|
||||||
4.0f/3.0f, 0.85f, Toolkit.getDefaultToolkit().getScreenSize());
|
|
||||||
GraphicsUtilities.centerInContainer(frame,
|
|
||||||
Toolkit.getDefaultToolkit().getScreenSize());
|
|
||||||
frame.setVisible(true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
|
|
||||||
/** Helper class for locating a program counter. Indicates the
|
|
||||||
confidence of the find. */
|
|
||||||
|
|
||||||
public class PCFinder {
|
|
||||||
public static final int LOW_CONFIDENCE = 1;
|
|
||||||
public static final int HIGH_CONFIDENCE = 2;
|
|
||||||
|
|
||||||
public static class Info {
|
|
||||||
private String name;
|
|
||||||
private long offset;
|
|
||||||
private int confidence;
|
|
||||||
|
|
||||||
public Info(String name, long offset, int confidence) {
|
|
||||||
this.name = name;
|
|
||||||
this.offset = offset;
|
|
||||||
this.confidence = confidence;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** May be null */
|
|
||||||
public String getName() { return name; }
|
|
||||||
|
|
||||||
/** If this is -1, a symbol could not be found, and the offset
|
|
||||||
should not be shown */
|
|
||||||
public long getOffset() { return offset; }
|
|
||||||
|
|
||||||
/** PCFinder.LOW_CONFIDENCE or PCFinder.HIGH_CONFIDENCE */
|
|
||||||
public int getConfidence() { return confidence; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Passed loadobject may be null in which case the returned Info
|
|
||||||
object has low confidence */
|
|
||||||
public static Info findPC(Address pc, LoadObject lo, CDebugger dbg) {
|
|
||||||
if (lo == null) {
|
|
||||||
return new Info(null, -1, LOW_CONFIDENCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// First try debug info
|
|
||||||
BlockSym sym = lo.debugInfoForPC(pc);
|
|
||||||
while (sym != null) {
|
|
||||||
if (sym.isFunction()) {
|
|
||||||
// Highest confidence
|
|
||||||
return new Info(sym.toString(), pc.minus(sym.getAddress()), HIGH_CONFIDENCE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now try looking up symbol in loadobject
|
|
||||||
|
|
||||||
// FIXME: must add support for mapfiles on Win32 and try looking
|
|
||||||
// up there first if possible. Should we hide that behind
|
|
||||||
// LoadObject.closestSymbolToPC and have the ClosestSymbol return
|
|
||||||
// confidence? I think so. On Solaris there is no notion of a
|
|
||||||
// mapfile, and the confidence for closestSymbolToPC will be high
|
|
||||||
// instead of low.
|
|
||||||
|
|
||||||
int confidence = HIGH_CONFIDENCE;
|
|
||||||
|
|
||||||
ClosestSymbol cs = lo.closestSymbolToPC(pc);
|
|
||||||
if (cs != null) {
|
|
||||||
// FIXME: currently low confidence (only on Win32)
|
|
||||||
return new Info(cs.getName() + "()", cs.getOffset(), LOW_CONFIDENCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Unknown location
|
|
||||||
return new Info(dbg.getNameOfFile(lo.getName()).toUpperCase() +
|
|
||||||
"! " + pc + "()", -1, HIGH_CONFIDENCE);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
|
|
||||||
/** Scans a .java file for the package that it is in. */
|
|
||||||
|
|
||||||
public class PackageScanner {
|
|
||||||
|
|
||||||
public PackageScanner() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public String scan(String filename) {
|
|
||||||
return scan(new File(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns the String comprising the package name of the classes in
|
|
||||||
this .java file. Returns the (non-null) empty string if any
|
|
||||||
error occurs or if the classes are in the unnamed package. */
|
|
||||||
public String scan(File file) {
|
|
||||||
BufferedReader buf = null;
|
|
||||||
String res = "";
|
|
||||||
try {
|
|
||||||
buf = new BufferedReader(new FileReader(file));
|
|
||||||
StreamTokenizer tok = new StreamTokenizer(buf);
|
|
||||||
tok.slashStarComments(true);
|
|
||||||
tok.slashSlashComments(true);
|
|
||||||
if (tok.nextToken() != StreamTokenizer.TT_WORD) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
if (!tok.sval.equals("package")) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
if (tok.nextToken() != StreamTokenizer.TT_WORD) {
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
res = tok.sval;
|
|
||||||
return res;
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
return res;
|
|
||||||
} catch (IOException e) {
|
|
||||||
return res;
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
if (buf != null) {
|
|
||||||
buf.close();
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
if (args.length != 1) {
|
|
||||||
usage();
|
|
||||||
}
|
|
||||||
|
|
||||||
System.out.println(new PackageScanner().scan(args[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void usage() {
|
|
||||||
System.err.println("Usage: java PackageScanner <.java file name>");
|
|
||||||
System.err.println("Prints package the .java file is in to stdout.");
|
|
||||||
System.exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,173 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.util.*;
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.table.*;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
|
|
||||||
/** Displays registers in a window. FIXME: this will need more work to
|
|
||||||
understand and handle register windows. */
|
|
||||||
|
|
||||||
public class RegisterPanel extends JPanel {
|
|
||||||
private java.util.List/*<RegisterInfo>*/ registers;
|
|
||||||
private AbstractTableModel dataModel;
|
|
||||||
private boolean valid;
|
|
||||||
private boolean editable;
|
|
||||||
private String nullAddressString;
|
|
||||||
private ThreadProxy curThread;
|
|
||||||
private JTable table;
|
|
||||||
|
|
||||||
static class RegisterInfo {
|
|
||||||
private String name;
|
|
||||||
private Address value;
|
|
||||||
|
|
||||||
RegisterInfo(String name, Address value) {
|
|
||||||
this.name = name;
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getName() { return name; }
|
|
||||||
Address getValue() { return value; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegisterPanel() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
registers = new ArrayList();
|
|
||||||
|
|
||||||
dataModel = new AbstractTableModel() {
|
|
||||||
public int getColumnCount() { return 2; }
|
|
||||||
public int getRowCount() { return registers.size(); }
|
|
||||||
public String getColumnName(int col) {
|
|
||||||
switch (col) {
|
|
||||||
case 0:
|
|
||||||
return "Register Name";
|
|
||||||
case 1:
|
|
||||||
return "Register Value";
|
|
||||||
default:
|
|
||||||
throw new RuntimeException("Index " + col + " out of bounds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public Object getValueAt(int row, int col) {
|
|
||||||
RegisterInfo info = (RegisterInfo) registers.get(row);
|
|
||||||
|
|
||||||
switch (col) {
|
|
||||||
case 0:
|
|
||||||
return info.getName();
|
|
||||||
case 1:
|
|
||||||
if (valid) {
|
|
||||||
Address val = info.getValue();
|
|
||||||
if (val != null) {
|
|
||||||
return val;
|
|
||||||
} else {
|
|
||||||
return nullAddressString;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return "-";
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public boolean isCellEditable(int row, int col) {
|
|
||||||
if (col == 0) return false;
|
|
||||||
if (!valid) return false;
|
|
||||||
if (curThread == null) return false;
|
|
||||||
if (!curThread.canSetContext()) return false;
|
|
||||||
|
|
||||||
// FIXME: add listener to watch for register changes
|
|
||||||
// return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Build user interface
|
|
||||||
setLayout(new BorderLayout());
|
|
||||||
table = new JTable(dataModel);
|
|
||||||
table.setCellSelectionEnabled(true);
|
|
||||||
table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
|
||||||
table.setDragEnabled(true);
|
|
||||||
JTableHeader header = table.getTableHeader();
|
|
||||||
header.setReorderingAllowed(false);
|
|
||||||
JScrollPane scrollPane = new JScrollPane(table);
|
|
||||||
add(scrollPane, BorderLayout.CENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** Updates the register panel with the register set from the
|
|
||||||
specified thread. Call this when the process has been suspended
|
|
||||||
and the current thread has been set. FIXME: this interface will
|
|
||||||
need to change to support register windows. */
|
|
||||||
public void update(ThreadProxy curThread) {
|
|
||||||
this.curThread = curThread;
|
|
||||||
ThreadContext context = curThread.getContext();
|
|
||||||
editable = curThread.canSetContext();
|
|
||||||
registers.clear();
|
|
||||||
for (int i = 0; i < context.getNumRegisters(); i++) {
|
|
||||||
String name = context.getRegisterName(i);
|
|
||||||
Address addr = context.getRegisterAsAddress(i);
|
|
||||||
if ((nullAddressString == null) && (addr != null)) {
|
|
||||||
String addrStr = addr.toString();
|
|
||||||
StringBuffer buf = new StringBuffer();
|
|
||||||
buf.append("0x");
|
|
||||||
int len = addrStr.length() - 2;
|
|
||||||
for (int j = 0; j < len; j++) {
|
|
||||||
buf.append("0");
|
|
||||||
}
|
|
||||||
nullAddressString = buf.toString();
|
|
||||||
}
|
|
||||||
registers.add(new RegisterInfo(name, addr));
|
|
||||||
}
|
|
||||||
valid = true;
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
dataModel.fireTableDataChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clears the registers' values. Call this when the processs has
|
|
||||||
been resumed. */
|
|
||||||
public void clear() {
|
|
||||||
valid = false;
|
|
||||||
nullAddressString = null;
|
|
||||||
SwingUtilities.invokeLater(new Runnable() {
|
|
||||||
public void run() {
|
|
||||||
dataModel.fireTableDataChanged();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setFont(Font font) {
|
|
||||||
super.setFont(font);
|
|
||||||
if (table != null) {
|
|
||||||
table.setFont(font);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
|
|
||||||
/** This class describes a frame in a stack trace. It abstracts over
|
|
||||||
C/C++ and Java frames. */
|
|
||||||
|
|
||||||
public class StackTraceEntry {
|
|
||||||
private CFrame cFrame;
|
|
||||||
private CDebugger dbg;
|
|
||||||
private JavaVFrame javaFrame;
|
|
||||||
private String value; // What is displayed in a stack trace
|
|
||||||
// For merging C and Java stack traces.
|
|
||||||
// For more precise stack traces, should probably have a way to
|
|
||||||
// convert a CFrame to a sun.jvm.hotspot.runtime.Frame. For now,
|
|
||||||
// doing similar algorithm to jdbx (which does not have intimate
|
|
||||||
// knowledge of the VM).
|
|
||||||
private boolean isUnknownCFrame;
|
|
||||||
|
|
||||||
public StackTraceEntry(CFrame cFrame, CDebugger dbg) {
|
|
||||||
this.cFrame = cFrame;
|
|
||||||
this.dbg = dbg;
|
|
||||||
computeValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public StackTraceEntry(JavaVFrame javaFrame) {
|
|
||||||
this.javaFrame = javaFrame;
|
|
||||||
computeValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isCFrame() { return (cFrame != null); }
|
|
||||||
public boolean isJavaFrame() { return (javaFrame != null); }
|
|
||||||
public CFrame getCFrame() { return cFrame; }
|
|
||||||
public JavaVFrame getJavaFrame() { return javaFrame; }
|
|
||||||
public boolean isUnknownCFrame() { return isUnknownCFrame; }
|
|
||||||
public String toString() {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void computeValue() {
|
|
||||||
isUnknownCFrame = true;
|
|
||||||
value = "<unknown>";
|
|
||||||
if (cFrame != null) {
|
|
||||||
PCFinder.Info info = PCFinder.findPC(cFrame.pc(), cFrame.loadObjectForPC(), dbg);
|
|
||||||
if (info.getName() != null) {
|
|
||||||
value = "(C) " + info.getName();
|
|
||||||
isUnknownCFrame = false;
|
|
||||||
if (info.getConfidence() == PCFinder.LOW_CONFIDENCE) {
|
|
||||||
value = value + " (?)";
|
|
||||||
}
|
|
||||||
if (info.getOffset() >= 0) {
|
|
||||||
value = value + " + 0x" + Long.toHexString(info.getOffset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (javaFrame != null) {
|
|
||||||
isUnknownCFrame = false;
|
|
||||||
Method m = javaFrame.getMethod();
|
|
||||||
value = "(J) " + m.externalNameAndSignature();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,115 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.*;
|
|
||||||
import java.util.*;
|
|
||||||
import javax.swing.*;
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
import sun.jvm.hotspot.ui.*;
|
|
||||||
|
|
||||||
/** This panel contains a ListBox with all of the stack frames in a
|
|
||||||
given thread. When a given entry is selected, an event is
|
|
||||||
fired. */
|
|
||||||
|
|
||||||
public class StackTracePanel extends JPanel {
|
|
||||||
public interface Listener {
|
|
||||||
public void frameChanged(CFrame fr, JavaVFrame jfr);
|
|
||||||
}
|
|
||||||
|
|
||||||
class Model extends AbstractListModel implements ComboBoxModel {
|
|
||||||
private Object selectedItem;
|
|
||||||
public Object getElementAt(int index) {
|
|
||||||
if (trace == null) return null;
|
|
||||||
return trace.get(index);
|
|
||||||
}
|
|
||||||
public int getSize() {
|
|
||||||
if (trace == null) return 0;
|
|
||||||
return trace.size();
|
|
||||||
}
|
|
||||||
public Object getSelectedItem() {
|
|
||||||
return selectedItem;
|
|
||||||
}
|
|
||||||
public void setSelectedItem(Object item) {
|
|
||||||
selectedItem = item;
|
|
||||||
}
|
|
||||||
public void dataChanged() {
|
|
||||||
fireContentsChanged(this, 0, trace.size());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private java.util.List trace;
|
|
||||||
private Model model;
|
|
||||||
private JComboBox list;
|
|
||||||
private java.util.List listeners;
|
|
||||||
|
|
||||||
public StackTracePanel() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
model = new Model();
|
|
||||||
|
|
||||||
// Build user interface
|
|
||||||
setLayout(new BorderLayout());
|
|
||||||
setBorder(GraphicsUtilities.newBorder(5));
|
|
||||||
list = new JComboBox(model);
|
|
||||||
list.setPrototypeDisplayValue("ZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
|
|
||||||
add(list, BorderLayout.CENTER);
|
|
||||||
|
|
||||||
// Add selection listener
|
|
||||||
list.addItemListener(new ItemListener() {
|
|
||||||
public void itemStateChanged(ItemEvent e) {
|
|
||||||
if (e.getStateChange() == ItemEvent.SELECTED) {
|
|
||||||
fireFrameChanged();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Takes a List of StackTraceEntry objects */
|
|
||||||
public void setTrace(java.util.List trace) {
|
|
||||||
this.trace = trace;
|
|
||||||
model.dataChanged();
|
|
||||||
list.setSelectedIndex(0);
|
|
||||||
fireFrameChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(Listener listener) {
|
|
||||||
if (listeners == null) {
|
|
||||||
listeners = new ArrayList();
|
|
||||||
}
|
|
||||||
listeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void fireFrameChanged() {
|
|
||||||
if (listeners != null) {
|
|
||||||
StackTraceEntry entry = (StackTraceEntry) trace.get(list.getSelectedIndex());
|
|
||||||
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
|
|
||||||
((Listener) iter.next()).frameChanged(entry.getCFrame(), entry.getJavaFrame());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,237 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import java.awt.event.*;
|
|
||||||
import java.util.*;
|
|
||||||
import javax.swing.*;
|
|
||||||
import javax.swing.table.*;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
import sun.jvm.hotspot.ui.*;
|
|
||||||
|
|
||||||
// NOTE: this class was not placed in sun.jvm.hotspot.ui to prevent
|
|
||||||
// mixing components designed for C and C++ debugging with the ones
|
|
||||||
// that work with the core serviceability agent functionality (which
|
|
||||||
// does not require that the CDebugger interface be implemented).
|
|
||||||
|
|
||||||
/** The ThreadListPanel is used for C and C++ debugging and can
|
|
||||||
visualize all threads in the target process. The caller passes in
|
|
||||||
a CDebugger attached to the target process and can request that
|
|
||||||
JavaThreads' associations with these underlying threads be
|
|
||||||
displayed; this option is only valid when attached to a HotSpot
|
|
||||||
JVM and when the {@link sun.jvm.hotspot.runtime.VM} has been
|
|
||||||
initialized. */
|
|
||||||
|
|
||||||
public class ThreadListPanel extends JPanel {
|
|
||||||
/** Listener which can be added to receive "Set Focus" events */
|
|
||||||
public static interface Listener {
|
|
||||||
/** ThreadProxy will always be provided; JavaThread will only be
|
|
||||||
present if displayJavaThreads was specified in the constructor
|
|
||||||
for the panel and the thread was a JavaThread. */
|
|
||||||
public void setFocus(ThreadProxy thread, JavaThread jthread);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ThreadInfo {
|
|
||||||
private ThreadProxy thread;
|
|
||||||
// Distinguish between PC == null and no top frame
|
|
||||||
private boolean gotPC;
|
|
||||||
private Address pc;
|
|
||||||
private String location;
|
|
||||||
private JavaThread javaThread;
|
|
||||||
private String javaThreadName;
|
|
||||||
|
|
||||||
public ThreadInfo(ThreadProxy thread, CDebugger dbg, JavaThread jthread) {
|
|
||||||
this.thread = thread;
|
|
||||||
this.location = "<unknown>";
|
|
||||||
CFrame fr = dbg.topFrameForThread(thread);
|
|
||||||
if (fr != null) {
|
|
||||||
gotPC = true;
|
|
||||||
pc = fr.pc();
|
|
||||||
PCFinder.Info info = PCFinder.findPC(pc, fr.loadObjectForPC(), dbg);
|
|
||||||
if (info.getName() != null) {
|
|
||||||
location = info.getName();
|
|
||||||
if (info.getConfidence() == PCFinder.LOW_CONFIDENCE) {
|
|
||||||
location = location + " (?)";
|
|
||||||
}
|
|
||||||
if (info.getOffset() < 0) {
|
|
||||||
location = location + " + 0x" + Long.toHexString(info.getOffset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (jthread != null) {
|
|
||||||
javaThread = jthread;
|
|
||||||
javaThreadName = jthread.getThreadName();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ThreadProxy getThread() { return thread; }
|
|
||||||
public boolean hasPC() { return gotPC; }
|
|
||||||
public Address getPC() { return pc; }
|
|
||||||
public String getLocation() { return location; }
|
|
||||||
public boolean isJavaThread() { return (javaThread != null); }
|
|
||||||
public JavaThread getJavaThread() { return javaThread; }
|
|
||||||
public String getJavaThreadName() { return javaThreadName; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// List<ThreadInfo>
|
|
||||||
private java.util.List threadList;
|
|
||||||
private JTable table;
|
|
||||||
private AbstractTableModel dataModel;
|
|
||||||
// List<Listener>
|
|
||||||
private java.util.List listeners;
|
|
||||||
|
|
||||||
/** Takes a CDebugger from which the thread list is queried.
|
|
||||||
displayJavaThreads must only be set to true if the debugger is
|
|
||||||
attached to a HotSpot JVM and if the VM has already been
|
|
||||||
initialized. */
|
|
||||||
public ThreadListPanel(CDebugger dbg, final boolean displayJavaThreads) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
Map threadToJavaThreadMap = null;
|
|
||||||
if (displayJavaThreads) {
|
|
||||||
// Collect Java threads from virtual machine and insert them in
|
|
||||||
// table for later querying
|
|
||||||
threadToJavaThreadMap = new HashMap();
|
|
||||||
Threads threads = VM.getVM().getThreads();
|
|
||||||
for (JavaThread thr = threads.first(); thr != null; thr = thr.next()) {
|
|
||||||
threadToJavaThreadMap.put(thr.getThreadProxy(), thr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
java.util.List/*<ThreadProxy>*/ threads = dbg.getThreadList();
|
|
||||||
threadList = new ArrayList(threads.size());
|
|
||||||
for (Iterator iter = threads.iterator(); iter.hasNext(); ) {
|
|
||||||
ThreadProxy thr = (ThreadProxy) iter.next();
|
|
||||||
JavaThread jthr = null;
|
|
||||||
if (displayJavaThreads) {
|
|
||||||
jthr = (JavaThread) threadToJavaThreadMap.get(thr);
|
|
||||||
}
|
|
||||||
threadList.add(new ThreadInfo(thr, dbg, jthr));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thread ID, current PC, current symbol, Java Thread, [Java thread name]
|
|
||||||
dataModel = new AbstractTableModel() {
|
|
||||||
public int getColumnCount() { return (displayJavaThreads ? 5 : 3); }
|
|
||||||
public int getRowCount() { return threadList.size(); }
|
|
||||||
public String getColumnName(int col) {
|
|
||||||
switch (col) {
|
|
||||||
case 0:
|
|
||||||
return "Thread ID";
|
|
||||||
case 1:
|
|
||||||
return "PC";
|
|
||||||
case 2:
|
|
||||||
return "Location";
|
|
||||||
case 3:
|
|
||||||
return "Java?";
|
|
||||||
case 4:
|
|
||||||
return "Java Thread Name";
|
|
||||||
default:
|
|
||||||
throw new RuntimeException("Index " + col + " out of bounds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public Object getValueAt(int row, int col) {
|
|
||||||
ThreadInfo info = (ThreadInfo) threadList.get(row);
|
|
||||||
|
|
||||||
switch (col) {
|
|
||||||
case 0:
|
|
||||||
return info.getThread();
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
if (info.hasPC()) {
|
|
||||||
return info.getPC();
|
|
||||||
}
|
|
||||||
return "<no frames on stack>";
|
|
||||||
}
|
|
||||||
case 2:
|
|
||||||
return info.getLocation();
|
|
||||||
case 3:
|
|
||||||
if (info.isJavaThread()) {
|
|
||||||
return "Yes";
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
case 4:
|
|
||||||
if (info.isJavaThread()) {
|
|
||||||
return info.getJavaThreadName();
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
throw new RuntimeException("Index (" + col + ", " + row + ") out of bounds");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Build user interface
|
|
||||||
setLayout(new BorderLayout());
|
|
||||||
table = new JTable(dataModel);
|
|
||||||
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
|
|
||||||
JTableHeader header = table.getTableHeader();
|
|
||||||
header.setReorderingAllowed(false);
|
|
||||||
table.setRowSelectionAllowed(true);
|
|
||||||
table.setColumnSelectionAllowed(false);
|
|
||||||
JScrollPane scrollPane = new JScrollPane(table);
|
|
||||||
add(scrollPane, BorderLayout.CENTER);
|
|
||||||
if (threadList.size() > 0) {
|
|
||||||
table.setRowSelectionInterval(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
JButton button = new JButton("Set Focus");
|
|
||||||
button.addActionListener(new ActionListener() {
|
|
||||||
public void actionPerformed(ActionEvent e) {
|
|
||||||
int i = table.getSelectedRow();
|
|
||||||
if (i < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ThreadInfo info = (ThreadInfo) threadList.get(i);
|
|
||||||
for (Iterator iter = listeners.iterator(); iter.hasNext(); ) {
|
|
||||||
((Listener) iter.next()).setFocus(info.getThread(), info.getJavaThread());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
JPanel focusPanel = new JPanel();
|
|
||||||
focusPanel.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 0));
|
|
||||||
focusPanel.setLayout(new BoxLayout(focusPanel, BoxLayout.Y_AXIS));
|
|
||||||
focusPanel.add(Box.createGlue());
|
|
||||||
focusPanel.add(button);
|
|
||||||
focusPanel.add(Box.createGlue());
|
|
||||||
add(focusPanel, BorderLayout.EAST);
|
|
||||||
|
|
||||||
// FIXME: make listener model for the debugger so if the user
|
|
||||||
// specifies a mapfile for or path to a given DSO later we can
|
|
||||||
// update our state
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addListener(Listener l) {
|
|
||||||
if (listeners == null) {
|
|
||||||
listeners = new ArrayList();
|
|
||||||
}
|
|
||||||
listeners.add(l);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,252 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot;
|
|
||||||
|
|
||||||
import java.awt.*;
|
|
||||||
import javax.swing.*;
|
|
||||||
import java.util.*;
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.bugspot.tree.*;
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.*;
|
|
||||||
import sun.jvm.hotspot.ui.treetable.*;
|
|
||||||
|
|
||||||
/** Manages display of a set of local variables in a frame, or the
|
|
||||||
contents of the "this" pointer */
|
|
||||||
|
|
||||||
public class VariablePanel extends JPanel {
|
|
||||||
private JTreeTable treeTable;
|
|
||||||
private SimpleTreeTableModel model;
|
|
||||||
private SimpleTreeGroupNode root;
|
|
||||||
|
|
||||||
public VariablePanel() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
model = new SimpleTreeTableModel();
|
|
||||||
model.setValuesEditable(false);
|
|
||||||
root = new SimpleTreeGroupNode();
|
|
||||||
model.setRoot(root);
|
|
||||||
treeTable = new JTreeTable(model);
|
|
||||||
treeTable.setRootVisible(false);
|
|
||||||
treeTable.setShowsRootHandles(true);
|
|
||||||
treeTable.setShowsIcons(false);
|
|
||||||
treeTable.setTreeEditable(false);
|
|
||||||
treeTable.getTableHeader().setReorderingAllowed(false);
|
|
||||||
treeTable.setCellSelectionEnabled(true);
|
|
||||||
treeTable.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
|
||||||
treeTable.setDragEnabled(true);
|
|
||||||
JScrollPane sp = new JScrollPane(treeTable);
|
|
||||||
sp.getViewport().setBackground(Color.white);
|
|
||||||
|
|
||||||
setLayout(new BorderLayout());
|
|
||||||
add(sp, BorderLayout.CENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clear the contents of this VariablePanel */
|
|
||||||
public void clear() {
|
|
||||||
root.removeAllChildren();
|
|
||||||
model.fireTreeStructureChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update the contents of this VariablePanel from the given CFrame */
|
|
||||||
public void update(CFrame fr) {
|
|
||||||
// Collect locals
|
|
||||||
CCollector coll = new CCollector();
|
|
||||||
fr.iterateLocals(coll);
|
|
||||||
update(coll);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update the contents of this VariablePanel from the given JavaVFrame */
|
|
||||||
public void update(JavaVFrame jfr) {
|
|
||||||
Method m = jfr.getMethod();
|
|
||||||
if (!m.hasLocalVariableTable()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int bci = jfr.getBCI();
|
|
||||||
// Get local variable table
|
|
||||||
LocalVariableTableElement[] locals = m.getLocalVariableTable();
|
|
||||||
// Get locals as StackValueCollection
|
|
||||||
StackValueCollection coll = jfr.getLocals();
|
|
||||||
root.removeAllChildren();
|
|
||||||
// See which locals are live
|
|
||||||
for (int i = 0; i < locals.length; i++) {
|
|
||||||
LocalVariableTableElement local = locals[i];
|
|
||||||
if (local.getStartBCI() <= bci && bci < local.getStartBCI() + local.getLength()) {
|
|
||||||
// Valid; add it
|
|
||||||
SimpleTreeNode node = null;
|
|
||||||
Symbol name = null;
|
|
||||||
try {
|
|
||||||
name = m.getConstants().getSymbolAt(local.getNameCPIndex());
|
|
||||||
if (name == null) {
|
|
||||||
System.err.println("Null name at slot " +
|
|
||||||
local.getNameCPIndex() +
|
|
||||||
" for local variable at slot " +
|
|
||||||
local.getSlot());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("Unable to fetch name at slot " +
|
|
||||||
local.getNameCPIndex() +
|
|
||||||
" for local variable at slot " +
|
|
||||||
local.getSlot());
|
|
||||||
e.printStackTrace();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
sun.jvm.hotspot.oops.NamedFieldIdentifier f =
|
|
||||||
new sun.jvm.hotspot.oops.NamedFieldIdentifier(name.asString());
|
|
||||||
Symbol descriptor = null;
|
|
||||||
try {
|
|
||||||
descriptor = m.getConstants().getSymbolAt(local.getDescriptorCPIndex());
|
|
||||||
} catch (Exception e) {
|
|
||||||
System.err.println("Unable to fetch descriptor at slot " +
|
|
||||||
local.getDescriptorCPIndex() +
|
|
||||||
" for local variable " + f.getName() +
|
|
||||||
" at slot " + local.getSlot());
|
|
||||||
e.printStackTrace();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor != null) {
|
|
||||||
switch (descriptor.getByteAt(0)) {
|
|
||||||
case 'F': {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.FloatTreeNodeAdapter(coll.floatAt(local.getSlot()), f, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'D': {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.DoubleTreeNodeAdapter(coll.doubleAt(local.getSlot()), f, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'C': {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.CharTreeNodeAdapter((char) coll.intAt(local.getSlot()), f, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'B':
|
|
||||||
case 'S':
|
|
||||||
case 'I': {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.intAt(local.getSlot()), f, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'Z': {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.BooleanTreeNodeAdapter(
|
|
||||||
((coll.intAt(local.getSlot()) != 0) ? true : false), f, true
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'J': {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.LongTreeNodeAdapter(coll.longAt(local.getSlot()), f, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: {
|
|
||||||
try {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.OopTreeNodeAdapter(
|
|
||||||
VM.getVM().getObjectHeap().newOop(coll.oopHandleAt(local.getSlot())), f, true
|
|
||||||
);
|
|
||||||
} catch (AddressException e) {
|
|
||||||
node = new sun.jvm.hotspot.ui.tree.FieldTreeNodeAdapter(f, true) {
|
|
||||||
public int getChildCount() { return 0; }
|
|
||||||
public SimpleTreeNode getChild(int i) { return null; }
|
|
||||||
public boolean isLeaf() { return false; }
|
|
||||||
public int getIndexOfChild(SimpleTreeNode child) { return 0; }
|
|
||||||
public String getValue() {
|
|
||||||
return "<Bad oop>";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node != null) {
|
|
||||||
root.addChild(node);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
model.fireTreeStructureChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Update the contents of this VariablePanel from the given "this"
|
|
||||||
pointer of the given type */
|
|
||||||
public void update(Address thisAddr, Type type) {
|
|
||||||
// Collect fields
|
|
||||||
CCollector coll = new CCollector();
|
|
||||||
type.iterateObject(thisAddr, coll);
|
|
||||||
update(coll);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void update(CCollector coll) {
|
|
||||||
root.removeAllChildren();
|
|
||||||
for (int i = 0; i < coll.getNumChildren(); i++) {
|
|
||||||
root.addChild(coll.getChild(i));
|
|
||||||
}
|
|
||||||
model.fireTreeStructureChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
static class CCollector extends DefaultObjectVisitor {
|
|
||||||
private java.util.List children;
|
|
||||||
|
|
||||||
public CCollector() {
|
|
||||||
children = new ArrayList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getNumChildren() {
|
|
||||||
return children.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild(int i) {
|
|
||||||
return (SimpleTreeNode) children.get(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doBit(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
public void doInt(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.LongTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
public void doEnum(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, long val, String enumName) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.EnumTreeNodeAdapter(enumName, val, f, true));
|
|
||||||
}
|
|
||||||
public void doFloat(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, float val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.FloatTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
public void doDouble(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, double val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.DoubleTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
public void doPointer(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
public void doArray(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
public void doRef(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.AddressTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
public void doCompound(sun.jvm.hotspot.debugger.cdbg.FieldIdentifier f, Address val) {
|
|
||||||
children.add(new sun.jvm.hotspot.bugspot.tree.ObjectTreeNodeAdapter(val, f, true));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot.tree;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
|
|
||||||
|
|
||||||
/** Encapsulates a float value in a tree handled by SimpleTreeModel */
|
|
||||||
|
|
||||||
public class AddressTreeNodeAdapter extends FieldTreeNodeAdapter {
|
|
||||||
private Address val;
|
|
||||||
|
|
||||||
public AddressTreeNodeAdapter(Address val, FieldIdentifier id) {
|
|
||||||
this(val, id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public AddressTreeNodeAdapter(Address val, FieldIdentifier id, boolean treeTableMode) {
|
|
||||||
super(id, treeTableMode);
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChildCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild(int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeaf() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndexOfChild(SimpleTreeNode child) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
if (val != null) {
|
|
||||||
return val.toString();
|
|
||||||
}
|
|
||||||
return "NULL";
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot.tree;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
|
|
||||||
|
|
||||||
/** Encapsulates a double value in a tree handled by SimpleTreeModel */
|
|
||||||
|
|
||||||
public class DoubleTreeNodeAdapter extends FieldTreeNodeAdapter {
|
|
||||||
private double val;
|
|
||||||
|
|
||||||
public DoubleTreeNodeAdapter(double val, FieldIdentifier id) {
|
|
||||||
this(val, id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DoubleTreeNodeAdapter(double val, FieldIdentifier id, boolean treeTableMode) {
|
|
||||||
super(id, treeTableMode);
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChildCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild(int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeaf() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndexOfChild(SimpleTreeNode child) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return Double.toString(val);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot.tree;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
|
|
||||||
|
|
||||||
/** Encapsulates an enumerated value in a tree handled by SimpleTreeModel */
|
|
||||||
|
|
||||||
public class EnumTreeNodeAdapter extends FieldTreeNodeAdapter {
|
|
||||||
private long val;
|
|
||||||
private String enumName;
|
|
||||||
|
|
||||||
public EnumTreeNodeAdapter(String enumName, long val, FieldIdentifier id) {
|
|
||||||
this(enumName, val, id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EnumTreeNodeAdapter(String enumName, long val, FieldIdentifier id, boolean treeTableMode) {
|
|
||||||
super(id, treeTableMode);
|
|
||||||
this.enumName = enumName;
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChildCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild(int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeaf() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndexOfChild(SimpleTreeNode child) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
if (enumName != null) {
|
|
||||||
return enumName;
|
|
||||||
} else {
|
|
||||||
return Long.toString(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot.tree;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
|
|
||||||
|
|
||||||
/** Abstract base class for all adapters for fields of C/C++ objects */
|
|
||||||
|
|
||||||
public abstract class FieldTreeNodeAdapter implements SimpleTreeNode {
|
|
||||||
private FieldIdentifier id;
|
|
||||||
private boolean treeTableMode;
|
|
||||||
|
|
||||||
/** The identifier may be null, i.e., for the root of the tree */
|
|
||||||
public FieldTreeNodeAdapter(FieldIdentifier id, boolean treeTableMode) {
|
|
||||||
this.id = id;
|
|
||||||
this.treeTableMode = treeTableMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FieldIdentifier getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Defaults to false in subclasses */
|
|
||||||
public boolean getTreeTableMode() {
|
|
||||||
return treeTableMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type getType() {
|
|
||||||
return getID().getType();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
if (getID() != null) {
|
|
||||||
return getID().toString();
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toString() {
|
|
||||||
if (treeTableMode) {
|
|
||||||
return getName();
|
|
||||||
} else {
|
|
||||||
if (getID() != null) {
|
|
||||||
return getName() + ": " + getValue();
|
|
||||||
} else {
|
|
||||||
return getValue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot.tree;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
|
|
||||||
|
|
||||||
/** Encapsulates a float value in a tree handled by SimpleTreeModel */
|
|
||||||
|
|
||||||
public class FloatTreeNodeAdapter extends FieldTreeNodeAdapter {
|
|
||||||
private float val;
|
|
||||||
|
|
||||||
public FloatTreeNodeAdapter(float val, FieldIdentifier id) {
|
|
||||||
this(val, id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public FloatTreeNodeAdapter(float val, FieldIdentifier id, boolean treeTableMode) {
|
|
||||||
super(id, treeTableMode);
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChildCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild(int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeaf() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndexOfChild(SimpleTreeNode child) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return Float.toString(val);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot.tree;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
|
|
||||||
|
|
||||||
/** Encapsulates a long value in a tree handled by SimpleTreeModel */
|
|
||||||
|
|
||||||
public class LongTreeNodeAdapter extends FieldTreeNodeAdapter {
|
|
||||||
private long val;
|
|
||||||
|
|
||||||
public LongTreeNodeAdapter(long val, FieldIdentifier id) {
|
|
||||||
this(val, id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public LongTreeNodeAdapter(long val, FieldIdentifier id, boolean treeTableMode) {
|
|
||||||
super(id, treeTableMode);
|
|
||||||
this.val = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChildCount() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild(int index) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeaf() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndexOfChild(SimpleTreeNode child) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
return Long.toString(val);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,216 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.bugspot.tree;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.debugger.cdbg.*;
|
|
||||||
import sun.jvm.hotspot.ui.tree.SimpleTreeNode;
|
|
||||||
|
|
||||||
/** An adapter class which allows C/C++ objects to be displayed in a
|
|
||||||
tree via the SimpleTreeNode interface. */
|
|
||||||
|
|
||||||
public class ObjectTreeNodeAdapter extends FieldTreeNodeAdapter {
|
|
||||||
// Address of object
|
|
||||||
private Address addr;
|
|
||||||
|
|
||||||
/** The address may be null (for object fields of objcets which are
|
|
||||||
null). The FieldIdentifier should not be null. treeTableMode
|
|
||||||
defaults to false. */
|
|
||||||
public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id) {
|
|
||||||
this(addr, id, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The address may be null (for object fields of objcets which are
|
|
||||||
null). The FieldIdentifier should not be null. */
|
|
||||||
public ObjectTreeNodeAdapter(Address addr, FieldIdentifier id, boolean treeTableMode) {
|
|
||||||
super(id, treeTableMode);
|
|
||||||
this.addr = addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChildCount() {
|
|
||||||
if (addr == null) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Counter c = new Counter();
|
|
||||||
getType().iterateObject(addr, c);
|
|
||||||
return c.getNumFields();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild(int index) {
|
|
||||||
if (addr == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Fetcher f = new Fetcher(index);
|
|
||||||
getType().iterateObject(addr, f);
|
|
||||||
return f.getChild();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isLeaf() {
|
|
||||||
return (addr == null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndexOfChild(SimpleTreeNode child) {
|
|
||||||
FieldIdentifier id = ((FieldTreeNodeAdapter) child).getID();
|
|
||||||
Finder f = new Finder(id);
|
|
||||||
getType().iterateObject(addr, f);
|
|
||||||
return f.getIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getValue() {
|
|
||||||
if (addr != null) {
|
|
||||||
return addr.toString();
|
|
||||||
}
|
|
||||||
return "NULL";
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Should be used only once, then have the number of fields
|
|
||||||
fetched. */
|
|
||||||
static class Counter extends DefaultObjectVisitor {
|
|
||||||
private int numFields;
|
|
||||||
|
|
||||||
public int getNumFields() {
|
|
||||||
return numFields;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doBit(FieldIdentifier f, long val) { ++numFields; }
|
|
||||||
public void doInt(FieldIdentifier f, long val) { ++numFields; }
|
|
||||||
public void doEnum(FieldIdentifier f, long val, String enumName) { ++numFields; }
|
|
||||||
public void doFloat(FieldIdentifier f, float val) { ++numFields; }
|
|
||||||
public void doDouble(FieldIdentifier f, double val) { ++numFields; }
|
|
||||||
public void doPointer(FieldIdentifier f, Address val) { ++numFields; }
|
|
||||||
public void doArray(FieldIdentifier f, Address val) { ++numFields; }
|
|
||||||
public void doRef(FieldIdentifier f, Address val) { ++numFields; }
|
|
||||||
public void doCompound(FieldIdentifier f, Address addr) { ++numFields; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Creates a new SimpleTreeNode for the given field. */
|
|
||||||
class Fetcher extends DefaultObjectVisitor {
|
|
||||||
private int index;
|
|
||||||
private int curField;
|
|
||||||
private SimpleTreeNode child;
|
|
||||||
|
|
||||||
public Fetcher(int index) {
|
|
||||||
this.index = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleTreeNode getChild() {
|
|
||||||
return child;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doBit(FieldIdentifier f, long val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new LongTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doInt(FieldIdentifier f, long val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new LongTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doEnum(FieldIdentifier f, long val, String enumName) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new EnumTreeNodeAdapter(enumName, val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doFloat(FieldIdentifier f, float val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new FloatTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doDouble(FieldIdentifier f, double val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new DoubleTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doPointer(FieldIdentifier f, Address val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doArray(FieldIdentifier f, Address val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doRef(FieldIdentifier f, Address val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new AddressTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doCompound(FieldIdentifier f, Address val) {
|
|
||||||
if (curField == index) {
|
|
||||||
child = new ObjectTreeNodeAdapter(val, f, getTreeTableMode());
|
|
||||||
}
|
|
||||||
++curField;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Finds the index of the given FieldIdentifier. */
|
|
||||||
static class Finder extends DefaultObjectVisitor {
|
|
||||||
private FieldIdentifier id;
|
|
||||||
private int curField;
|
|
||||||
private int index = -1;
|
|
||||||
|
|
||||||
public Finder(FieldIdentifier id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns -1 if not found */
|
|
||||||
public int getIndex() {
|
|
||||||
return index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void doBit(FieldIdentifier f, long val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doInt(FieldIdentifier f, long val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doEnum(FieldIdentifier f, long val,
|
|
||||||
String enumName) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doFloat(FieldIdentifier f, float val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doDouble(FieldIdentifier f, double val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doPointer(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doArray(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doRef(FieldIdentifier f, Address val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
public void doCompound(FieldIdentifier f,
|
|
||||||
Address val) { if (f.equals(id)) { index = curField; } ++curField; }
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.livejvm;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
|
|
||||||
public class BreakpointEvent extends Event {
|
|
||||||
private Oop thread;
|
|
||||||
private Oop clazz;
|
|
||||||
private JNIid method;
|
|
||||||
private int location;
|
|
||||||
|
|
||||||
public BreakpointEvent(Oop thread,
|
|
||||||
Oop clazz,
|
|
||||||
JNIid method,
|
|
||||||
int location) {
|
|
||||||
super(Event.Type.BREAKPOINT);
|
|
||||||
this.thread = thread;
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.method = method;
|
|
||||||
this.location = location;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Oop thread() { return thread; }
|
|
||||||
public Oop clazz() { return clazz; }
|
|
||||||
public JNIid methodID() { return method; }
|
|
||||||
public int location() { return location; }
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.livejvm;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
|
|
||||||
class CStringAccessor {
|
|
||||||
private Address addr;
|
|
||||||
private int bufLen;
|
|
||||||
|
|
||||||
CStringAccessor(Address addr, int bufLen) {
|
|
||||||
this.addr = addr;
|
|
||||||
this.bufLen = bufLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getValue() throws DebuggerException {
|
|
||||||
int len = 0;
|
|
||||||
while ((addr.getCIntegerAt(len, 1, true) != 0) && (len < bufLen)) {
|
|
||||||
++len;
|
|
||||||
}
|
|
||||||
byte[] res = new byte[len];
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
res[i] = (byte) addr.getCIntegerAt(i, 1, true);
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return new String(res, "US-ASCII");
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new DebuggerException("Unable to use US-ASCII encoding");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setValue(String value) throws DebuggerException {
|
|
||||||
try {
|
|
||||||
byte[] data = value.getBytes("US-ASCII");
|
|
||||||
if (data.length >= bufLen) {
|
|
||||||
throw new DebuggerException("String too long");
|
|
||||||
}
|
|
||||||
for (int i = 0; i < data.length; i++) {
|
|
||||||
addr.setCIntegerAt(i, 1, data[i]);
|
|
||||||
}
|
|
||||||
addr.setCIntegerAt(data.length, 1, 0);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new DebuggerException("Unable to use US-ASCII encoding");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.livejvm;
|
|
||||||
|
|
||||||
public class Event {
|
|
||||||
public static class Type {
|
|
||||||
private Type() {}
|
|
||||||
public static final Type BREAKPOINT = new Type();
|
|
||||||
public static final Type EXCEPTION = new Type();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Type type;
|
|
||||||
|
|
||||||
public Event(Type type) {
|
|
||||||
this.type = type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Type getType() { return type; }
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.livejvm;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
|
|
||||||
public class ExceptionEvent extends Event {
|
|
||||||
private Oop thread;
|
|
||||||
private Oop clazz;
|
|
||||||
private JNIid method;
|
|
||||||
private int location;
|
|
||||||
private Oop exception;
|
|
||||||
private Oop catchClass;
|
|
||||||
private JNIid catchMethod;
|
|
||||||
private int catchLocation;
|
|
||||||
|
|
||||||
public ExceptionEvent(Oop thread,
|
|
||||||
Oop clazz,
|
|
||||||
JNIid method,
|
|
||||||
int location,
|
|
||||||
Oop exception,
|
|
||||||
Oop catchClass,
|
|
||||||
JNIid catchMethod,
|
|
||||||
int catchLocation) {
|
|
||||||
super(Event.Type.EXCEPTION);
|
|
||||||
this.thread = thread;
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.method = method;
|
|
||||||
this.location = location;
|
|
||||||
this.exception = exception;
|
|
||||||
this.catchClass = catchClass;
|
|
||||||
this.catchMethod = catchMethod;
|
|
||||||
this.catchLocation = catchLocation;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Oop thread() { return thread; }
|
|
||||||
public Oop clazz() { return clazz; }
|
|
||||||
public JNIid methodID() { return method; }
|
|
||||||
public int location() { return location; }
|
|
||||||
public Oop exception() { return exception; }
|
|
||||||
public Oop catchClass() { return catchClass; }
|
|
||||||
public JNIid catchMethodID() { return catchMethod; }
|
|
||||||
public int catchLocation() { return catchLocation; }
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.livejvm;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
import sun.jvm.hotspot.utilities.*;
|
|
||||||
|
|
||||||
class JNIHandleAccessor {
|
|
||||||
private Address addr;
|
|
||||||
private ObjectHeap heap;
|
|
||||||
|
|
||||||
JNIHandleAccessor(Address addr, ObjectHeap heap) {
|
|
||||||
this.addr = addr;
|
|
||||||
this.heap = heap;
|
|
||||||
}
|
|
||||||
|
|
||||||
Oop getValue() {
|
|
||||||
// Accessing the contents of the JNIHandle is a double dereference
|
|
||||||
Address handle = addr.getAddressAt(0);
|
|
||||||
if (handle == null) return null;
|
|
||||||
return heap.newOop(handle.getOopHandleAt(0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void setValue(Oop value) {
|
|
||||||
Address handle = addr.getAddressAt(0);
|
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
|
||||||
Assert.that(handle != null, "Must have valid global JNI handle for setting");
|
|
||||||
}
|
|
||||||
handle.setOopHandleAt(0, value.getHandle());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,415 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package sun.jvm.hotspot.livejvm;
|
|
||||||
|
|
||||||
import sun.jvm.hotspot.debugger.*;
|
|
||||||
import sun.jvm.hotspot.oops.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
|
||||||
|
|
||||||
/** Provides Java programming language-level interaction with a live
|
|
||||||
Java HotSpot VM via the use of the SA's JVMDI module. This is an
|
|
||||||
experimental mechanism. The BugSpot debugger should be converted
|
|
||||||
to use the JVMDI/JDWP-based JDI implementation for live process
|
|
||||||
interaction once the JDI binding for the SA is complete. */
|
|
||||||
|
|
||||||
public class ServiceabilityAgentJVMDIModule {
|
|
||||||
private Debugger dbg;
|
|
||||||
private String[] saLibNames;
|
|
||||||
private String saLibName;
|
|
||||||
private boolean attached;
|
|
||||||
|
|
||||||
private boolean suspended;
|
|
||||||
|
|
||||||
private static final int JVMDI_EVENT_BREAKPOINT = 2;
|
|
||||||
private static final int JVMDI_EVENT_EXCEPTION = 4;
|
|
||||||
|
|
||||||
private static long timeoutMillis = 3000;
|
|
||||||
|
|
||||||
// Values in target process
|
|
||||||
// Events sent from VM to SA
|
|
||||||
private CIntegerAccessor saAttached;
|
|
||||||
private CIntegerAccessor saEventPending;
|
|
||||||
private CIntegerAccessor saEventKind;
|
|
||||||
// Exception events
|
|
||||||
private JNIHandleAccessor saExceptionThread;
|
|
||||||
private JNIHandleAccessor saExceptionClass;
|
|
||||||
private JNIid saExceptionMethod;
|
|
||||||
private CIntegerAccessor saExceptionLocation;
|
|
||||||
private JNIHandleAccessor saExceptionException;
|
|
||||||
private JNIHandleAccessor saExceptionCatchClass;
|
|
||||||
private JNIid saExceptionCatchMethod;
|
|
||||||
private CIntegerAccessor saExceptionCatchLocation;
|
|
||||||
// Breakpoint events
|
|
||||||
private JNIHandleAccessor saBreakpointThread;
|
|
||||||
private JNIHandleAccessor saBreakpointClass;
|
|
||||||
private JNIid saBreakpointMethod;
|
|
||||||
private CIntegerAccessor saBreakpointLocation;
|
|
||||||
// Commands sent by the SA to the VM
|
|
||||||
private int SA_CMD_SUSPEND_ALL;
|
|
||||||
private int SA_CMD_RESUME_ALL;
|
|
||||||
private int SA_CMD_TOGGLE_BREAKPOINT;
|
|
||||||
private int SA_CMD_BUF_SIZE;
|
|
||||||
private CIntegerAccessor saCmdPending;
|
|
||||||
private CIntegerAccessor saCmdType;
|
|
||||||
private CIntegerAccessor saCmdResult;
|
|
||||||
private CStringAccessor saCmdResultErrMsg;
|
|
||||||
// Toggle breakpoint command arguments
|
|
||||||
private CStringAccessor saCmdBkptSrcFileName;
|
|
||||||
private CStringAccessor saCmdBkptPkgName;
|
|
||||||
private CIntegerAccessor saCmdBkptLineNumber;
|
|
||||||
private CIntegerAccessor saCmdBkptResWasError;
|
|
||||||
private CIntegerAccessor saCmdBkptResLineNumber;
|
|
||||||
private CIntegerAccessor saCmdBkptResBCI;
|
|
||||||
private CIntegerAccessor saCmdBkptResWasSet;
|
|
||||||
private CStringAccessor saCmdBkptResMethodName;
|
|
||||||
private CStringAccessor saCmdBkptResMethodSig;
|
|
||||||
|
|
||||||
public ServiceabilityAgentJVMDIModule(Debugger dbg, String[] saLibNames) {
|
|
||||||
this.dbg = dbg;
|
|
||||||
this.saLibNames = saLibNames;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether a call to attach() should complete without an
|
|
||||||
exception. */
|
|
||||||
public boolean canAttach() {
|
|
||||||
return setupLookup("SA_CMD_SUSPEND_ALL");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Attempt to initiate a connection with the JVMDI module in the
|
|
||||||
target VM. */
|
|
||||||
public void attach() throws DebuggerException {
|
|
||||||
if (!canAttach()) {
|
|
||||||
throw new DebuggerException("Unable to initiate symbol lookup in SA's JVMDI module");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (attached) {
|
|
||||||
throw new DebuggerException("Already attached");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attempt to look up well-known symbols in the target VM.
|
|
||||||
SA_CMD_SUSPEND_ALL = lookupConstInt("SA_CMD_SUSPEND_ALL");
|
|
||||||
SA_CMD_RESUME_ALL = lookupConstInt("SA_CMD_RESUME_ALL");
|
|
||||||
SA_CMD_TOGGLE_BREAKPOINT = lookupConstInt("SA_CMD_TOGGLE_BREAKPOINT");
|
|
||||||
SA_CMD_BUF_SIZE = lookupConstInt("SA_CMD_BUF_SIZE");
|
|
||||||
|
|
||||||
saAttached = lookupCInt("saAttached");
|
|
||||||
saEventPending = lookupCInt("saEventPending");
|
|
||||||
saEventKind = lookupCInt("saEventKind");
|
|
||||||
saCmdPending = lookupCInt("saCmdPending");
|
|
||||||
saCmdType = lookupCInt("saCmdType");
|
|
||||||
saCmdResult = lookupCInt("saCmdResult");
|
|
||||||
saCmdResultErrMsg = lookupCString("saCmdResultErrMsg", SA_CMD_BUF_SIZE);
|
|
||||||
// Toggling of breakpoints
|
|
||||||
saCmdBkptSrcFileName = lookupCString("saCmdBkptSrcFileName", SA_CMD_BUF_SIZE);
|
|
||||||
saCmdBkptPkgName = lookupCString("saCmdBkptPkgName", SA_CMD_BUF_SIZE);
|
|
||||||
saCmdBkptLineNumber = lookupCInt("saCmdBkptLineNumber");
|
|
||||||
saCmdBkptResWasError = lookupCInt("saCmdBkptResWasError");
|
|
||||||
saCmdBkptResLineNumber = lookupCInt("saCmdBkptResLineNumber");
|
|
||||||
saCmdBkptResBCI = lookupCInt("saCmdBkptResBCI");
|
|
||||||
saCmdBkptResWasSet = lookupCInt("saCmdBkptResWasSet");
|
|
||||||
saCmdBkptResMethodName = lookupCString("saCmdBkptResMethodName", SA_CMD_BUF_SIZE);
|
|
||||||
saCmdBkptResMethodSig = lookupCString("saCmdBkptResMethodSig", SA_CMD_BUF_SIZE);
|
|
||||||
|
|
||||||
// Check for existence of symbols needed later
|
|
||||||
// FIXME: should probably cache these since we can't support the
|
|
||||||
// -Xrun module or the VM getting unloaded anyway
|
|
||||||
lookup("saExceptionThread");
|
|
||||||
lookup("saExceptionClass");
|
|
||||||
lookup("saExceptionMethod");
|
|
||||||
lookup("saExceptionLocation");
|
|
||||||
lookup("saExceptionException");
|
|
||||||
lookup("saExceptionCatchClass");
|
|
||||||
lookup("saExceptionCatchMethod");
|
|
||||||
lookup("saExceptionCatchLocation");
|
|
||||||
lookup("saBreakpointThread");
|
|
||||||
lookup("saBreakpointClass");
|
|
||||||
lookup("saBreakpointMethod");
|
|
||||||
lookup("saBreakpointLocation");
|
|
||||||
|
|
||||||
saAttached.setValue(1);
|
|
||||||
attached = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void detach() {
|
|
||||||
saAttached.setValue(0);
|
|
||||||
attached = false;
|
|
||||||
saLibName = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the timeout value (in milliseconds) for the VM to reply to
|
|
||||||
commands. Once this timeout has elapsed, the VM is assumed to
|
|
||||||
have disconnected. Defaults to 3000 milliseconds (3 seconds). */
|
|
||||||
public void setCommandTimeout(long millis) {
|
|
||||||
timeoutMillis = millis;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Get the timeout value (in milliseconds) for the VM to reply to
|
|
||||||
commands. Once this timeout has elapsed, the VM is assumed to
|
|
||||||
have disconnected. Defaults to 3000 milliseconds (3 seconds). */
|
|
||||||
public long getCommandTimeout() {
|
|
||||||
return timeoutMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether a Java debug event is pending */
|
|
||||||
public boolean eventPending() {
|
|
||||||
return (saEventPending.getValue() != 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Poll for event; returns null if none pending. */
|
|
||||||
public Event eventPoll() {
|
|
||||||
if (saEventPending.getValue() == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
int kind = (int) saEventKind.getValue();
|
|
||||||
switch (kind) {
|
|
||||||
case JVMDI_EVENT_EXCEPTION: {
|
|
||||||
JNIHandleAccessor thread = lookupJNIHandle("saExceptionThread");
|
|
||||||
JNIHandleAccessor clazz = lookupJNIHandle("saExceptionClass");
|
|
||||||
JNIid method = lookupJNIid("saExceptionMethod");
|
|
||||||
CIntegerAccessor location = lookupCInt("saExceptionLocation");
|
|
||||||
JNIHandleAccessor exception = lookupJNIHandle("saExceptionException");
|
|
||||||
JNIHandleAccessor catchClass = lookupJNIHandle("saExceptionCatchClass");
|
|
||||||
JNIid catchMethod = lookupJNIid("saExceptionCatchMethod");
|
|
||||||
CIntegerAccessor catchLocation = lookupCInt("saExceptionCatchLocation");
|
|
||||||
return new ExceptionEvent(thread.getValue(), clazz.getValue(), method,
|
|
||||||
(int) location.getValue(), exception.getValue(),
|
|
||||||
catchClass.getValue(), catchMethod, (int) catchLocation.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
case JVMDI_EVENT_BREAKPOINT: {
|
|
||||||
JNIHandleAccessor thread = lookupJNIHandle("saBreakpointThread");
|
|
||||||
JNIHandleAccessor clazz = lookupJNIHandle("saBreakpointClass");
|
|
||||||
JNIid method = lookupJNIid("saBreakpointMethod");
|
|
||||||
CIntegerAccessor location = lookupCInt("saBreakpointLocation");
|
|
||||||
return new BreakpointEvent(thread.getValue(), clazz.getValue(),
|
|
||||||
method, (int) location.getValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
throw new DebuggerException("Unsupported event type " + kind);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Continue past current event */
|
|
||||||
public void eventContinue() {
|
|
||||||
saEventPending.setValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Suspend all Java threads in the target VM. Throws
|
|
||||||
DebuggerException if the VM disconnected. */
|
|
||||||
public void suspend() {
|
|
||||||
saCmdType.setValue(SA_CMD_SUSPEND_ALL);
|
|
||||||
saCmdPending.setValue(1);
|
|
||||||
waitForCommandCompletion();
|
|
||||||
suspended = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Resume all Java threads in the target VM. Throws
|
|
||||||
DebuggerException if the VM disconnected. */
|
|
||||||
public void resume() {
|
|
||||||
saCmdType.setValue(SA_CMD_RESUME_ALL);
|
|
||||||
saCmdPending.setValue(1);
|
|
||||||
waitForCommandCompletion();
|
|
||||||
suspended = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether all Java threads have been suspended via this
|
|
||||||
interface. */
|
|
||||||
public boolean isSuspended() {
|
|
||||||
return suspended;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Information about toggling of breakpoints */
|
|
||||||
public static class BreakpointToggleResult {
|
|
||||||
private boolean success;
|
|
||||||
private String errMsg;
|
|
||||||
private int lineNumber;
|
|
||||||
private int bci;
|
|
||||||
private boolean wasSet;
|
|
||||||
private String methodName;
|
|
||||||
private String methodSig;
|
|
||||||
|
|
||||||
/** Success constructor */
|
|
||||||
public BreakpointToggleResult(int lineNumber, int bci, boolean wasSet,
|
|
||||||
String methodName, String methodSig) {
|
|
||||||
this.lineNumber = lineNumber;
|
|
||||||
this.bci = bci;
|
|
||||||
this.wasSet = wasSet;
|
|
||||||
this.methodName = methodName;
|
|
||||||
this.methodSig = methodSig;
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Failure constructor */
|
|
||||||
public BreakpointToggleResult(String errMsg) {
|
|
||||||
this.errMsg = errMsg;
|
|
||||||
success = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Indicates whether this represents a successful return or not */
|
|
||||||
public boolean getSuccess() { return success; }
|
|
||||||
|
|
||||||
/** Valid only if getSuccess() returns false */
|
|
||||||
public String getErrMsg() { return errMsg; }
|
|
||||||
|
|
||||||
/** Line number at which breakpoint toggle occurred; valid only if
|
|
||||||
getSuccess() returns true. */
|
|
||||||
public int getLineNumber() { return lineNumber; }
|
|
||||||
|
|
||||||
/** BCI at which breakpoint toggle occurred; valid only if
|
|
||||||
getSuccess() returns true. */
|
|
||||||
public int getBCI() { return bci; }
|
|
||||||
|
|
||||||
/** Indicates whether the breakpoint toggle was the set of a
|
|
||||||
breakpoint or not; valid only if getSuccess() returns true. */
|
|
||||||
public boolean getWasSet() { return wasSet; }
|
|
||||||
|
|
||||||
/** Method name in which the breakpoint toggle occurred; valid
|
|
||||||
only if getSuccess() returns true. */
|
|
||||||
public String getMethodName() { return methodName; }
|
|
||||||
|
|
||||||
/** Method signature in which the breakpoint toggle occurred;
|
|
||||||
valid only if getSuccess() returns true. */
|
|
||||||
public String getMethodSignature() { return methodSig; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Toggle a breakpoint. Throws DebuggerException if a real error
|
|
||||||
occurred; otherwise returns non-null BreakpointToggleResult. The
|
|
||||||
work of scanning the loaded classes is done in the target VM
|
|
||||||
because it turns out to be significantly faster than scanning
|
|
||||||
through the system dictionary from the SA, and interactivity
|
|
||||||
when setting breakpoints is important. */
|
|
||||||
public BreakpointToggleResult toggleBreakpoint(String srcFileName,
|
|
||||||
String pkgName,
|
|
||||||
int lineNo) {
|
|
||||||
saCmdBkptSrcFileName.setValue(srcFileName);
|
|
||||||
saCmdBkptPkgName.setValue(pkgName);
|
|
||||||
saCmdBkptLineNumber.setValue(lineNo);
|
|
||||||
saCmdType.setValue(SA_CMD_TOGGLE_BREAKPOINT);
|
|
||||||
saCmdPending.setValue(1);
|
|
||||||
if (waitForCommandCompletion(true)) {
|
|
||||||
return new BreakpointToggleResult((int) saCmdBkptResLineNumber.getValue(),
|
|
||||||
(int) saCmdBkptResBCI.getValue(),
|
|
||||||
(saCmdBkptResWasSet.getValue() != 0),
|
|
||||||
saCmdBkptResMethodName.getValue(),
|
|
||||||
saCmdBkptResMethodSig.getValue());
|
|
||||||
} else {
|
|
||||||
return new BreakpointToggleResult(saCmdResultErrMsg.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//----------------------------------------------------------------------
|
|
||||||
// Internals only below this point
|
|
||||||
//
|
|
||||||
|
|
||||||
private CIntegerAccessor lookupCInt(String symbolName) {
|
|
||||||
return new CIntegerAccessor(lookup(symbolName), 4, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private CStringAccessor lookupCString(String symbolName, int bufLen) {
|
|
||||||
return new CStringAccessor(lookup(symbolName), bufLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
private JNIHandleAccessor lookupJNIHandle(String symbolName) {
|
|
||||||
return new JNIHandleAccessor(lookup(symbolName), VM.getVM().getObjectHeap());
|
|
||||||
}
|
|
||||||
|
|
||||||
private JNIid lookupJNIid(String symbolName) {
|
|
||||||
Address idAddr = lookup(symbolName).getAddressAt(0);
|
|
||||||
if (idAddr == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return new JNIid(idAddr, VM.getVM().getObjectHeap());
|
|
||||||
}
|
|
||||||
|
|
||||||
private int lookupConstInt(String symbolName) {
|
|
||||||
Address addr = lookup(symbolName);
|
|
||||||
return (int) addr.getCIntegerAt(0, 4, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean setupLookup(String symbolName) {
|
|
||||||
if (saLibName == null) {
|
|
||||||
for (int i = 0; i < saLibNames.length; i++) {
|
|
||||||
Address addr = dbg.lookup(saLibNames[i], symbolName);
|
|
||||||
if (addr != null) {
|
|
||||||
saLibName = saLibNames[i];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Address lookup(String symbolName) {
|
|
||||||
if (saLibName == null) {
|
|
||||||
for (int i = 0; i < saLibNames.length; i++) {
|
|
||||||
Address addr = dbg.lookup(saLibNames[i], symbolName);
|
|
||||||
if (addr != null) {
|
|
||||||
saLibName = saLibNames[i];
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new DebuggerException("Unable to find symbol " + symbolName + " in any of the known names for the SA");
|
|
||||||
}
|
|
||||||
|
|
||||||
Address addr = dbg.lookup(saLibName, symbolName);
|
|
||||||
if (addr == null) {
|
|
||||||
throw new DebuggerException("Unable to find symbol " + symbolName + " in " + saLibName);
|
|
||||||
}
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void waitForCommandCompletion() {
|
|
||||||
waitForCommandCompletion(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns true if command succeeded, false if not */
|
|
||||||
private boolean waitForCommandCompletion(boolean forBreakpoint) {
|
|
||||||
long start = System.currentTimeMillis();
|
|
||||||
long cur = start;
|
|
||||||
while ((saCmdPending.getValue() != 0) &&
|
|
||||||
(cur - start < timeoutMillis)) {
|
|
||||||
try {
|
|
||||||
java.lang.Thread.currentThread().sleep(10);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
}
|
|
||||||
cur = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
if (saCmdPending.getValue() != 0) {
|
|
||||||
detach();
|
|
||||||
throw new DebuggerException("VM appears to have died");
|
|
||||||
}
|
|
||||||
boolean succeeded = saCmdResult.getValue() == 0;
|
|
||||||
if (!succeeded &&
|
|
||||||
(!forBreakpoint || saCmdBkptResWasError.getValue() != 0)) {
|
|
||||||
String err = saCmdResultErrMsg.getValue();
|
|
||||||
throw new DebuggerException("Error executing JVMDI command: " + err);
|
|
||||||
}
|
|
||||||
return succeeded;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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
|
||||||
@ -469,7 +469,6 @@ public class ConstantPool extends Metadata implements ClassConstants {
|
|||||||
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
|
case JVM_CONSTANT_UnresolvedClassInError: return "JVM_CONSTANT_UnresolvedClassInError";
|
||||||
case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError";
|
case JVM_CONSTANT_MethodHandleInError:return "JVM_CONSTANT_MethodHandleInError";
|
||||||
case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError";
|
case JVM_CONSTANT_MethodTypeInError: return "JVM_CONSTANT_MethodTypeInError";
|
||||||
case JVM_CONSTANT_Object: return "JVM_CONSTANT_Object";
|
|
||||||
}
|
}
|
||||||
throw new InternalError("Unknown tag: " + tag);
|
throw new InternalError("Unknown tag: " + tag);
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2002, 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,7 +67,6 @@ public interface ClassConstants
|
|||||||
public static final int JVM_CONSTANT_UnresolvedClassInError = 103; // Error tag due to resolution error
|
public static final int JVM_CONSTANT_UnresolvedClassInError = 103; // Error tag due to resolution error
|
||||||
public static final int JVM_CONSTANT_MethodHandleInError = 104; // Error tag due to resolution error
|
public static final int JVM_CONSTANT_MethodHandleInError = 104; // Error tag due to resolution error
|
||||||
public static final int JVM_CONSTANT_MethodTypeInError = 105; // Error tag due to resolution error
|
public static final int JVM_CONSTANT_MethodTypeInError = 105; // Error tag due to resolution error
|
||||||
public static final int JVM_CONSTANT_Object = 106; // Required for BoundMethodHandle arguments.
|
|
||||||
|
|
||||||
// 1.5 major/minor version numbers from JVM spec. 3rd edition
|
// 1.5 major/minor version numbers from JVM spec. 3rd edition
|
||||||
public static final short MAJOR_VERSION = 49;
|
public static final short MAJOR_VERSION = 49;
|
||||||
|
@ -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
|
||||||
@ -35,16 +35,16 @@ import sun.jvm.hotspot.tools.*;
|
|||||||
import sun.jvm.hotspot.utilities.*;
|
import sun.jvm.hotspot.utilities.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A command line tool to print perm. generation statistics.
|
A command line tool to print class loader statistics.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class PermStat extends Tool {
|
public class ClassLoaderStats extends Tool {
|
||||||
boolean verbose = true;
|
boolean verbose = true;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
PermStat ps = new PermStat();
|
ClassLoaderStats cls = new ClassLoaderStats();
|
||||||
ps.start(args);
|
cls.start(args);
|
||||||
ps.stop();
|
cls.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ClassData {
|
private static class ClassData {
|
@ -57,17 +57,18 @@ public class HeapSummary extends Tool {
|
|||||||
printGCAlgorithm(flagMap);
|
printGCAlgorithm(flagMap);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("Heap Configuration:");
|
System.out.println("Heap Configuration:");
|
||||||
printValue("MinHeapFreeRatio = ", getFlagValue("MinHeapFreeRatio", flagMap));
|
printValue("MinHeapFreeRatio = ", getFlagValue("MinHeapFreeRatio", flagMap));
|
||||||
printValue("MaxHeapFreeRatio = ", getFlagValue("MaxHeapFreeRatio", flagMap));
|
printValue("MaxHeapFreeRatio = ", getFlagValue("MaxHeapFreeRatio", flagMap));
|
||||||
printValMB("MaxHeapSize = ", getFlagValue("MaxHeapSize", flagMap));
|
printValMB("MaxHeapSize = ", getFlagValue("MaxHeapSize", flagMap));
|
||||||
printValMB("NewSize = ", getFlagValue("NewSize", flagMap));
|
printValMB("NewSize = ", getFlagValue("NewSize", flagMap));
|
||||||
printValMB("MaxNewSize = ", getFlagValue("MaxNewSize", flagMap));
|
printValMB("MaxNewSize = ", getFlagValue("MaxNewSize", flagMap));
|
||||||
printValMB("OldSize = ", getFlagValue("OldSize", flagMap));
|
printValMB("OldSize = ", getFlagValue("OldSize", flagMap));
|
||||||
printValue("NewRatio = ", getFlagValue("NewRatio", flagMap));
|
printValue("NewRatio = ", getFlagValue("NewRatio", flagMap));
|
||||||
printValue("SurvivorRatio = ", getFlagValue("SurvivorRatio", flagMap));
|
printValue("SurvivorRatio = ", getFlagValue("SurvivorRatio", flagMap));
|
||||||
printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap));
|
printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap));
|
||||||
printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap));
|
printValMB("ClassMetaspaceSize = ", getFlagValue("ClassMetaspaceSize", flagMap));
|
||||||
printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes());
|
printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap));
|
||||||
|
printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes());
|
||||||
|
|
||||||
System.out.println();
|
System.out.println();
|
||||||
System.out.println("Heap Usage:");
|
System.out.println("Heap Usage:");
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2004, 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
|
||||||
@ -45,7 +45,7 @@ public class JMap extends Tool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected String getCommandFlags() {
|
protected String getCommandFlags() {
|
||||||
return "-heap|-heap:format=b|-histo|-permstat|-finalizerinfo";
|
return "-heap|-heap:format=b|-histo|-clstats|-finalizerinfo";
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void printFlagsUsage() {
|
protected void printFlagsUsage() {
|
||||||
@ -53,14 +53,14 @@ public class JMap extends Tool {
|
|||||||
System.out.println(" -heap\tto print java heap summary");
|
System.out.println(" -heap\tto print java heap summary");
|
||||||
System.out.println(" -heap:format=b\tto dump java heap in hprof binary format");
|
System.out.println(" -heap:format=b\tto dump java heap in hprof binary format");
|
||||||
System.out.println(" -histo\tto print histogram of java object heap");
|
System.out.println(" -histo\tto print histogram of java object heap");
|
||||||
System.out.println(" -permstat\tto print permanent generation statistics");
|
System.out.println(" -clstats\tto print class loader statistics");
|
||||||
System.out.println(" -finalizerinfo\tto print information on objects awaiting finalization");
|
System.out.println(" -finalizerinfo\tto print information on objects awaiting finalization");
|
||||||
super.printFlagsUsage();
|
super.printFlagsUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final int MODE_HEAP_SUMMARY = 0;
|
public static final int MODE_HEAP_SUMMARY = 0;
|
||||||
public static final int MODE_HISTOGRAM = 1;
|
public static final int MODE_HISTOGRAM = 1;
|
||||||
public static final int MODE_PERMSTAT = 2;
|
public static final int MODE_CLSTATS = 2;
|
||||||
public static final int MODE_PMAP = 3;
|
public static final int MODE_PMAP = 3;
|
||||||
public static final int MODE_HEAP_GRAPH_HPROF_BIN = 4;
|
public static final int MODE_HEAP_GRAPH_HPROF_BIN = 4;
|
||||||
public static final int MODE_HEAP_GRAPH_GXL = 5;
|
public static final int MODE_HEAP_GRAPH_GXL = 5;
|
||||||
@ -78,8 +78,8 @@ public class JMap extends Tool {
|
|||||||
tool = new ObjectHistogram();
|
tool = new ObjectHistogram();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_PERMSTAT:
|
case MODE_CLSTATS:
|
||||||
tool = new PermStat();
|
tool = new ClassLoaderStats();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MODE_PMAP:
|
case MODE_PMAP:
|
||||||
@ -118,7 +118,9 @@ public class JMap extends Tool {
|
|||||||
} else if (modeFlag.equals("-histo")) {
|
} else if (modeFlag.equals("-histo")) {
|
||||||
mode = MODE_HISTOGRAM;
|
mode = MODE_HISTOGRAM;
|
||||||
} else if (modeFlag.equals("-permstat")) {
|
} else if (modeFlag.equals("-permstat")) {
|
||||||
mode = MODE_PERMSTAT;
|
mode = MODE_CLSTATS;
|
||||||
|
} else if (modeFlag.equals("-clstats")) {
|
||||||
|
mode = MODE_CLSTATS;
|
||||||
} else if (modeFlag.equals("-finalizerinfo")) {
|
} else if (modeFlag.equals("-finalizerinfo")) {
|
||||||
mode = MODE_FINALIZERINFO;
|
mode = MODE_FINALIZERINFO;
|
||||||
} else {
|
} else {
|
||||||
|
@ -58,10 +58,6 @@ public class PMap extends Tool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean requiresVM() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
PMap t = new PMap();
|
PMap t = new PMap();
|
||||||
t.start(args);
|
t.start(args);
|
||||||
|
@ -50,29 +50,23 @@ public class PStack extends Tool {
|
|||||||
|
|
||||||
public void run(PrintStream out) {
|
public void run(PrintStream out) {
|
||||||
Debugger dbg = getAgent().getDebugger();
|
Debugger dbg = getAgent().getDebugger();
|
||||||
run(out, dbg, getAgent().isJavaMode());
|
run(out, dbg);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run(PrintStream out, Debugger dbg) {
|
public void run(PrintStream out, Debugger dbg) {
|
||||||
run(out, dbg, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void run(PrintStream out, Debugger dbg, final boolean isJava) {
|
|
||||||
CDebugger cdbg = dbg.getCDebugger();
|
CDebugger cdbg = dbg.getCDebugger();
|
||||||
if (cdbg != null) {
|
if (cdbg != null) {
|
||||||
ConcurrentLocksPrinter concLocksPrinter = null;
|
ConcurrentLocksPrinter concLocksPrinter = null;
|
||||||
if (isJava) {
|
// compute and cache java Vframes.
|
||||||
// compute and cache java Vframes.
|
initJFrameCache();
|
||||||
initJFrameCache();
|
if (concurrentLocks) {
|
||||||
if (concurrentLocks) {
|
concLocksPrinter = new ConcurrentLocksPrinter();
|
||||||
concLocksPrinter = new ConcurrentLocksPrinter();
|
}
|
||||||
}
|
// print Java level deadlocks
|
||||||
// print Java level deadlocks
|
try {
|
||||||
try {
|
DeadlockDetector.print(out);
|
||||||
DeadlockDetector.print(out);
|
} catch (Exception exp) {
|
||||||
} catch (Exception exp) {
|
out.println("can't print deadlock information: " + exp.getMessage());
|
||||||
out.println("can't print deadlock information: " + exp.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List l = cdbg.getThreadList();
|
List l = cdbg.getThreadList();
|
||||||
@ -100,63 +94,59 @@ public class PStack extends Tool {
|
|||||||
}
|
}
|
||||||
out.println();
|
out.println();
|
||||||
} else {
|
} else {
|
||||||
if (isJava) {
|
// look for one or more java frames
|
||||||
// look for one or more java frames
|
String[] names = null;
|
||||||
String[] names = null;
|
// check interpreter frame
|
||||||
// check interpreter frame
|
Interpreter interp = VM.getVM().getInterpreter();
|
||||||
Interpreter interp = VM.getVM().getInterpreter();
|
if (interp.contains(pc)) {
|
||||||
if (interp.contains(pc)) {
|
names = getJavaNames(th, f.localVariableBase());
|
||||||
names = getJavaNames(th, f.localVariableBase());
|
// print codelet name if we can't determine method
|
||||||
// print codelet name if we can't determine method
|
if (names == null || names.length == 0) {
|
||||||
if (names == null || names.length == 0) {
|
out.print("<interpreter> ");
|
||||||
out.print("<interpreter> ");
|
InterpreterCodelet ic = interp.getCodeletContaining(pc);
|
||||||
InterpreterCodelet ic = interp.getCodeletContaining(pc);
|
if (ic != null) {
|
||||||
if (ic != null) {
|
String desc = ic.getDescription();
|
||||||
String desc = ic.getDescription();
|
if (desc != null) out.print(desc);
|
||||||
if (desc != null) out.print(desc);
|
}
|
||||||
}
|
out.println();
|
||||||
out.println();
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
// look for known code blobs
|
||||||
// look for known code blobs
|
CodeCache c = VM.getVM().getCodeCache();
|
||||||
CodeCache c = VM.getVM().getCodeCache();
|
if (c.contains(pc)) {
|
||||||
if (c.contains(pc)) {
|
CodeBlob cb = c.findBlobUnsafe(pc);
|
||||||
CodeBlob cb = c.findBlobUnsafe(pc);
|
if (cb.isNMethod()) {
|
||||||
if (cb.isNMethod()) {
|
names = getJavaNames(th, f.localVariableBase());
|
||||||
names = getJavaNames(th, f.localVariableBase());
|
// just print compiled code, if can't determine method
|
||||||
// just print compiled code, if can't determine method
|
if (names == null || names.length == 0) {
|
||||||
if (names == null || names.length == 0) {
|
out.println("<Unknown compiled code>");
|
||||||
out.println("<Unknown compiled code>");
|
}
|
||||||
}
|
} else if (cb.isBufferBlob()) {
|
||||||
} else if (cb.isBufferBlob()) {
|
out.println("<StubRoutines>");
|
||||||
out.println("<StubRoutines>");
|
} else if (cb.isRuntimeStub()) {
|
||||||
} else if (cb.isRuntimeStub()) {
|
out.println("<RuntimeStub>");
|
||||||
out.println("<RuntimeStub>");
|
} else if (cb.isDeoptimizationStub()) {
|
||||||
} else if (cb.isDeoptimizationStub()) {
|
out.println("<DeoptimizationStub>");
|
||||||
out.println("<DeoptimizationStub>");
|
} else if (cb.isUncommonTrapStub()) {
|
||||||
} else if (cb.isUncommonTrapStub()) {
|
out.println("<UncommonTrap>");
|
||||||
out.println("<UncommonTrap>");
|
} else if (cb.isExceptionStub()) {
|
||||||
} else if (cb.isExceptionStub()) {
|
out.println("<ExceptionStub>");
|
||||||
out.println("<ExceptionStub>");
|
} else if (cb.isSafepointStub()) {
|
||||||
} else if (cb.isSafepointStub()) {
|
out.println("<SafepointStub>");
|
||||||
out.println("<SafepointStub>");
|
} else {
|
||||||
} else {
|
out.println("<Unknown code blob>");
|
||||||
out.println("<Unknown code blob>");
|
}
|
||||||
}
|
} else {
|
||||||
} else {
|
printUnknown(out);
|
||||||
printUnknown(out);
|
}
|
||||||
}
|
}
|
||||||
}
|
// print java frames, if any
|
||||||
// print java frames, if any
|
if (names != null && names.length != 0) {
|
||||||
if (names != null && names.length != 0) {
|
// print java frame(s)
|
||||||
// print java frame(s)
|
for (int i = 0; i < names.length; i++) {
|
||||||
for (int i = 0; i < names.length; i++) {
|
out.println(names[i]);
|
||||||
out.println(names[i]);
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
|
||||||
printUnknown(out);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
f = f.sender(th);
|
f = f.sender(th);
|
||||||
}
|
}
|
||||||
@ -164,7 +154,7 @@ public class PStack extends Tool {
|
|||||||
exp.printStackTrace();
|
exp.printStackTrace();
|
||||||
// continue, may be we can do a better job for other threads
|
// continue, may be we can do a better job for other threads
|
||||||
}
|
}
|
||||||
if (isJava && concurrentLocks) {
|
if (concurrentLocks) {
|
||||||
JavaThread jthread = (JavaThread) proxyToThread.get(th);
|
JavaThread jthread = (JavaThread) proxyToThread.get(th);
|
||||||
if (jthread != null) {
|
if (jthread != null) {
|
||||||
concLocksPrinter.print(jthread, out);
|
concLocksPrinter.print(jthread, out);
|
||||||
@ -180,10 +170,6 @@ public class PStack extends Tool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean requiresVM() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
PStack t = new PStack();
|
PStack t = new PStack();
|
||||||
t.start(args);
|
t.start(args);
|
||||||
|
@ -27,7 +27,6 @@ package sun.jvm.hotspot.tools;
|
|||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.util.Hashtable;
|
import java.util.Hashtable;
|
||||||
import sun.jvm.hotspot.*;
|
import sun.jvm.hotspot.*;
|
||||||
import sun.jvm.hotspot.bugspot.*;
|
|
||||||
import sun.jvm.hotspot.runtime.*;
|
import sun.jvm.hotspot.runtime.*;
|
||||||
import sun.jvm.hotspot.debugger.*;
|
import sun.jvm.hotspot.debugger.*;
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ import sun.jvm.hotspot.debugger.*;
|
|||||||
// override run & code main as shown below.
|
// override run & code main as shown below.
|
||||||
|
|
||||||
public abstract class Tool implements Runnable {
|
public abstract class Tool implements Runnable {
|
||||||
private BugSpotAgent agent;
|
private HotSpotAgent agent;
|
||||||
private int debugeeType;
|
private int debugeeType;
|
||||||
|
|
||||||
// debugeeType is one of constants below
|
// debugeeType is one of constants below
|
||||||
@ -51,12 +50,7 @@ public abstract class Tool implements Runnable {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// whether this tool requires debuggee to be java process or core?
|
protected void setAgent(HotSpotAgent a) {
|
||||||
protected boolean requiresVM() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setAgent(BugSpotAgent a) {
|
|
||||||
agent = a;
|
agent = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +58,7 @@ public abstract class Tool implements Runnable {
|
|||||||
debugeeType = dt;
|
debugeeType = dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BugSpotAgent getAgent() {
|
protected HotSpotAgent getAgent() {
|
||||||
return agent;
|
return agent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +149,7 @@ public abstract class Tool implements Runnable {
|
|||||||
usage();
|
usage();
|
||||||
}
|
}
|
||||||
|
|
||||||
agent = new BugSpotAgent();
|
agent = new HotSpotAgent();
|
||||||
try {
|
try {
|
||||||
switch (debugeeType) {
|
switch (debugeeType) {
|
||||||
case DEBUGEE_PID:
|
case DEBUGEE_PID:
|
||||||
@ -198,33 +192,24 @@ public abstract class Tool implements Runnable {
|
|||||||
|
|
||||||
err.println("Debugger attached successfully.");
|
err.println("Debugger attached successfully.");
|
||||||
|
|
||||||
boolean isJava = agent.isJavaMode();
|
VM vm = VM.getVM();
|
||||||
if (isJava) {
|
if (vm.isCore()) {
|
||||||
VM vm = VM.getVM();
|
err.println("Core build detected.");
|
||||||
if (vm.isCore()) {
|
} else if (vm.isClientCompiler()) {
|
||||||
err.println("Core build detected.");
|
err.println("Client compiler detected.");
|
||||||
} else if (vm.isClientCompiler()) {
|
} else if (vm.isServerCompiler()) {
|
||||||
err.println("Client compiler detected.");
|
err.println("Server compiler detected.");
|
||||||
} else if (vm.isServerCompiler()) {
|
} else {
|
||||||
err.println("Server compiler detected.");
|
throw new RuntimeException("Fatal error: "
|
||||||
} else {
|
+ "should have been able to detect core/C1/C2 build");
|
||||||
throw new RuntimeException("Fatal error: " +
|
|
||||||
"should have been able to detect core/C1/C2 build");
|
|
||||||
}
|
|
||||||
|
|
||||||
String version = vm.getVMRelease();
|
|
||||||
if (version != null) {
|
|
||||||
err.print("JVM version is ");
|
|
||||||
err.println(version);
|
|
||||||
}
|
|
||||||
|
|
||||||
run();
|
|
||||||
} else { // not a java process or core
|
|
||||||
if (requiresVM()) {
|
|
||||||
err.println(getName() + " requires a java VM process/core!");
|
|
||||||
} else {
|
|
||||||
run();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String version = vm.getVMRelease();
|
||||||
|
if (version != null) {
|
||||||
|
err.print("JVM version is ");
|
||||||
|
err.println(version);
|
||||||
|
}
|
||||||
|
|
||||||
|
run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ import com.sun.java.swing.action.*;
|
|||||||
/**
|
/**
|
||||||
* This base class encapsulates many of the events that are fired from
|
* This base class encapsulates many of the events that are fired from
|
||||||
* the various panels in this directory so they can easily be plugged
|
* the various panels in this directory so they can easily be plugged
|
||||||
* in to different containing frameworks (HSDB, BugSpot).
|
* in to different containing frameworks (HSDB).
|
||||||
*/
|
*/
|
||||||
public class SAPanel extends JPanel {
|
public class SAPanel extends JPanel {
|
||||||
protected List listeners = new ArrayList();
|
protected List listeners = new ArrayList();
|
||||||
|
@ -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
|
||||||
@ -51,7 +51,6 @@ public class ConstantTag {
|
|||||||
private static final int JVM_CONSTANT_UnresolvedClassInError = 103; // Resolution failed
|
private static final int JVM_CONSTANT_UnresolvedClassInError = 103; // Resolution failed
|
||||||
private static final int JVM_CONSTANT_MethodHandleInError = 104; // Error tag due to resolution error
|
private static final int JVM_CONSTANT_MethodHandleInError = 104; // Error tag due to resolution error
|
||||||
private static final int JVM_CONSTANT_MethodTypeInError = 105; // Error tag due to resolution error
|
private static final int JVM_CONSTANT_MethodTypeInError = 105; // Error tag due to resolution error
|
||||||
private static final int JVM_CONSTANT_Object = 106; // Required for BoundMethodHandle arguments.
|
|
||||||
|
|
||||||
// JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure
|
// JVM_CONSTANT_MethodHandle subtypes //FIXME: connect these to data structure
|
||||||
private static int JVM_REF_getField = 1;
|
private static int JVM_REF_getField = 1;
|
||||||
@ -96,8 +95,6 @@ public class ConstantTag {
|
|||||||
public boolean isKlassIndex() { return tag == JVM_CONSTANT_ClassIndex; }
|
public boolean isKlassIndex() { return tag == JVM_CONSTANT_ClassIndex; }
|
||||||
public boolean isStringIndex() { return tag == JVM_CONSTANT_StringIndex; }
|
public boolean isStringIndex() { return tag == JVM_CONSTANT_StringIndex; }
|
||||||
|
|
||||||
public boolean isObject() { return tag == JVM_CONSTANT_Object; }
|
|
||||||
|
|
||||||
public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); }
|
public boolean isKlassReference() { return isKlassIndex() || isUnresolvedKlass(); }
|
||||||
public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); }
|
public boolean isFieldOrMethod() { return isField() || isMethod() || isInterfaceMethod(); }
|
||||||
public boolean isSymbol() { return isUtf8(); }
|
public boolean isSymbol() { return isUtf8(); }
|
||||||
@ -123,7 +120,6 @@ public class ConstantTag {
|
|||||||
case JVM_CONSTANT_StringIndex :
|
case JVM_CONSTANT_StringIndex :
|
||||||
case JVM_CONSTANT_MethodHandle :
|
case JVM_CONSTANT_MethodHandle :
|
||||||
case JVM_CONSTANT_MethodType :
|
case JVM_CONSTANT_MethodType :
|
||||||
case JVM_CONSTANT_Object :
|
|
||||||
return BasicType.T_OBJECT;
|
return BasicType.T_OBJECT;
|
||||||
default:
|
default:
|
||||||
throw new InternalError("unexpected tag: " + tag);
|
throw new InternalError("unexpected tag: " + tag);
|
||||||
|
@ -31,7 +31,6 @@ var sapkg = new Object();
|
|||||||
|
|
||||||
sapkg.hotspot = Packages.sun.jvm.hotspot;
|
sapkg.hotspot = Packages.sun.jvm.hotspot;
|
||||||
sapkg.asm = sapkg.hotspot.asm;
|
sapkg.asm = sapkg.hotspot.asm;
|
||||||
sapkg.bugspot = sapkg.hotspot.bugspot;
|
|
||||||
sapkg.c1 = sapkg.hotspot.c1;
|
sapkg.c1 = sapkg.hotspot.c1;
|
||||||
sapkg.code = sapkg.hotspot.code;
|
sapkg.code = sapkg.hotspot.code;
|
||||||
sapkg.compiler = sapkg.hotspot.compiler;
|
sapkg.compiler = sapkg.hotspot.compiler;
|
||||||
@ -40,7 +39,6 @@ sapkg.compiler = sapkg.hotspot.compiler;
|
|||||||
// sapkg.debugger = sapkg.hotspot.debugger;
|
// sapkg.debugger = sapkg.hotspot.debugger;
|
||||||
|
|
||||||
sapkg.interpreter = sapkg.hotspot.interpreter;
|
sapkg.interpreter = sapkg.hotspot.interpreter;
|
||||||
sapkg.livejvm = sapkg.hotspot.livejvm;
|
|
||||||
sapkg.jdi = sapkg.hotspot.jdi;
|
sapkg.jdi = sapkg.hotspot.jdi;
|
||||||
sapkg.memory = sapkg.hotspot.memory;
|
sapkg.memory = sapkg.hotspot.memory;
|
||||||
sapkg.oops = sapkg.hotspot.oops;
|
sapkg.oops = sapkg.hotspot.oops;
|
||||||
|
@ -1,601 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <vector>
|
|
||||||
#include "sa.hpp"
|
|
||||||
#include "jni.h"
|
|
||||||
#include "jvmdi.h"
|
|
||||||
|
|
||||||
#ifndef WIN32
|
|
||||||
#include <inttypes.h>
|
|
||||||
#else
|
|
||||||
typedef int int32_t;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
#define YIELD() Sleep(0)
|
|
||||||
#define SLEEP() Sleep(10)
|
|
||||||
#define vsnprintf _vsnprintf
|
|
||||||
#else
|
|
||||||
Error: please port YIELD() and SLEEP() macros to your platform
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using namespace std;
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
// //
|
|
||||||
// Exported "interface" for Java language-level interaction between //
|
|
||||||
// the SA and the VM. Note that the SA knows about the layout of //
|
|
||||||
// certain VM data structures and that knowledge is taken advantage //
|
|
||||||
// of in this code, although this interfaces with the VM via JVMDI. //
|
|
||||||
// //
|
|
||||||
//////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
/////////////////////////////////////
|
|
||||||
// //
|
|
||||||
// Events sent by the VM to the SA //
|
|
||||||
// //
|
|
||||||
/////////////////////////////////////
|
|
||||||
|
|
||||||
// Set by the SA when it attaches. Indicates that events should be
|
|
||||||
// posted via these exported variables, and that the VM should wait
|
|
||||||
// for those events to be acknowledged by the SA (via its setting
|
|
||||||
// saEventPending to 0).
|
|
||||||
JNIEXPORT volatile int32_t saAttached = 0;
|
|
||||||
|
|
||||||
// Set to nonzero value by the VM when an event has been posted; set
|
|
||||||
// back to 0 by the SA when it has processed that event.
|
|
||||||
JNIEXPORT volatile int32_t saEventPending = 0;
|
|
||||||
|
|
||||||
// Kind of the event (from jvmdi.h)
|
|
||||||
JNIEXPORT volatile int32_t saEventKind = 0;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Exception events
|
|
||||||
//
|
|
||||||
JNIEXPORT jthread saExceptionThread;
|
|
||||||
JNIEXPORT jclass saExceptionClass;
|
|
||||||
JNIEXPORT jmethodID saExceptionMethod;
|
|
||||||
JNIEXPORT int32_t saExceptionLocation;
|
|
||||||
JNIEXPORT jobject saExceptionException;
|
|
||||||
JNIEXPORT jclass saExceptionCatchClass;
|
|
||||||
JNIEXPORT jmethodID saExceptionCatchMethod;
|
|
||||||
JNIEXPORT int32_t saExceptionCatchLocation;
|
|
||||||
|
|
||||||
//
|
|
||||||
// Breakpoint events
|
|
||||||
//
|
|
||||||
JNIEXPORT jthread saBreakpointThread;
|
|
||||||
JNIEXPORT jclass saBreakpointClass;
|
|
||||||
JNIEXPORT jmethodID saBreakpointMethod;
|
|
||||||
JNIEXPORT jlocation saBreakpointLocation;
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
|
||||||
// //
|
|
||||||
// Commands sent by the SA to the VM //
|
|
||||||
// //
|
|
||||||
///////////////////////////////////////
|
|
||||||
|
|
||||||
extern JNIEXPORT const int32_t SA_CMD_SUSPEND_ALL = 0;
|
|
||||||
extern JNIEXPORT const int32_t SA_CMD_RESUME_ALL = 1;
|
|
||||||
extern JNIEXPORT const int32_t SA_CMD_TOGGLE_BREAKPOINT = 2;
|
|
||||||
extern JNIEXPORT const int32_t SA_CMD_BUF_SIZE = 1024;
|
|
||||||
|
|
||||||
// SA sets this to a nonzero value when it is requesting a command
|
|
||||||
// to be processed; VM sets it back to 0 when the command has been
|
|
||||||
// executed
|
|
||||||
JNIEXPORT volatile int32_t saCmdPending = 0;
|
|
||||||
|
|
||||||
// SA sets this to one of the manifest constants above to indicate
|
|
||||||
// the kind of command to be executed
|
|
||||||
JNIEXPORT volatile int32_t saCmdType = 0;
|
|
||||||
|
|
||||||
// VM sets this to 0 if the last command succeeded or a nonzero
|
|
||||||
// value if it failed
|
|
||||||
JNIEXPORT volatile int32_t saCmdResult = 0;
|
|
||||||
|
|
||||||
// If last command failed, this buffer will contain a descriptive
|
|
||||||
// error message
|
|
||||||
JNIEXPORT char saCmdResultErrMsg[SA_CMD_BUF_SIZE];
|
|
||||||
|
|
||||||
//
|
|
||||||
// Toggling of breakpoint command arguments.
|
|
||||||
//
|
|
||||||
// Originally there were separate set/clear breakpoint commands
|
|
||||||
// taking a class name, method name and signature, and the iteration
|
|
||||||
// through the debug information was done in the SA. It turns out
|
|
||||||
// that doing this work in the target VM is significantly faster,
|
|
||||||
// and since interactivity when setting and clearing breakpoints is
|
|
||||||
// important, the solution which resulted in more C/C++ code was used.
|
|
||||||
//
|
|
||||||
|
|
||||||
// Source file name
|
|
||||||
JNIEXPORT char saCmdBkptSrcFileName[SA_CMD_BUF_SIZE];
|
|
||||||
|
|
||||||
// Package name ('/' as separator instead of '.')
|
|
||||||
JNIEXPORT char saCmdBkptPkgName[SA_CMD_BUF_SIZE];
|
|
||||||
|
|
||||||
// Line number
|
|
||||||
JNIEXPORT int32_t saCmdBkptLineNumber;
|
|
||||||
|
|
||||||
// Output back to SA: indicator whether the last failure of a
|
|
||||||
// breakpoint toggle command was really an error or just a lack of
|
|
||||||
// debug information covering the requested line. 0 if not error.
|
|
||||||
// Valid only if saCmdResult != 0.
|
|
||||||
JNIEXPORT int32_t saCmdBkptResWasError;
|
|
||||||
|
|
||||||
// Output back to SA: resulting line number at which the breakpoint
|
|
||||||
// was set or cleared (valid only if saCmdResult == 0)
|
|
||||||
JNIEXPORT int32_t saCmdBkptResLineNumber;
|
|
||||||
|
|
||||||
// Output back to SA: resulting byte code index at which the
|
|
||||||
// breakpoint was set or cleared (valid only if saCmdResult == 0)
|
|
||||||
JNIEXPORT int32_t saCmdBkptResBCI;
|
|
||||||
|
|
||||||
// Output back to SA: indicator whether the breakpoint operation
|
|
||||||
// resulted in a set or cleared breakpoint; nonzero if set, zero if
|
|
||||||
// cleared (valid only if saCmdResult == 0)
|
|
||||||
JNIEXPORT int32_t saCmdBkptResWasSet;
|
|
||||||
|
|
||||||
// Output back to SA: method name the breakpoint was set in (valid
|
|
||||||
// only if saCmdResult == 0)
|
|
||||||
JNIEXPORT char saCmdBkptResMethodName[SA_CMD_BUF_SIZE];
|
|
||||||
|
|
||||||
// Output back to SA: method signature (JNI style) the breakpoint
|
|
||||||
// was set in (valid only if saCmdResult == 0)
|
|
||||||
JNIEXPORT char saCmdBkptResMethodSig[SA_CMD_BUF_SIZE];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Internal state
|
|
||||||
static JavaVM* jvm = NULL;
|
|
||||||
static JVMDI_Interface_1* jvmdi = NULL;
|
|
||||||
static jthread debugThreadObj = NULL;
|
|
||||||
static bool suspended = false;
|
|
||||||
static vector<jthread> suspendedThreads;
|
|
||||||
static JVMDI_RawMonitor eventLock = NULL;
|
|
||||||
|
|
||||||
class MonitorLocker {
|
|
||||||
private:
|
|
||||||
JVMDI_RawMonitor lock;
|
|
||||||
public:
|
|
||||||
MonitorLocker(JVMDI_RawMonitor lock) {
|
|
||||||
this->lock = lock;
|
|
||||||
if (lock != NULL) {
|
|
||||||
jvmdi->RawMonitorEnter(lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
~MonitorLocker() {
|
|
||||||
if (lock != NULL) {
|
|
||||||
jvmdi->RawMonitorExit(lock);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class JvmdiDeallocator {
|
|
||||||
private:
|
|
||||||
void* ptr;
|
|
||||||
public:
|
|
||||||
JvmdiDeallocator(void* ptr) {
|
|
||||||
this->ptr = ptr;
|
|
||||||
}
|
|
||||||
~JvmdiDeallocator() {
|
|
||||||
jvmdi->Deallocate((jbyte*) ptr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class JvmdiRefListDeallocator {
|
|
||||||
private:
|
|
||||||
JNIEnv* env;
|
|
||||||
jobject* refList;
|
|
||||||
jint refCount;
|
|
||||||
public:
|
|
||||||
JvmdiRefListDeallocator(JNIEnv* env, jobject* refList, jint refCount) {
|
|
||||||
this->env = env;
|
|
||||||
this->refList = refList;
|
|
||||||
this->refCount = refCount;
|
|
||||||
}
|
|
||||||
~JvmdiRefListDeallocator() {
|
|
||||||
for (int i = 0; i < refCount; i++) {
|
|
||||||
env->DeleteGlobalRef(refList[i]);
|
|
||||||
}
|
|
||||||
jvmdi->Deallocate((jbyte*) refList);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static void
|
|
||||||
stop(char* msg) {
|
|
||||||
fprintf(stderr, "%s", msg);
|
|
||||||
fprintf(stderr, "\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This fills in the command result error message, sets the command
|
|
||||||
// result to -1, and clears the pending command flag
|
|
||||||
static void
|
|
||||||
reportErrorToSA(const char* str, ...) {
|
|
||||||
va_list varargs;
|
|
||||||
va_start(varargs, str);
|
|
||||||
vsnprintf(saCmdResultErrMsg, sizeof(saCmdResultErrMsg), str, varargs);
|
|
||||||
va_end(varargs);
|
|
||||||
saCmdResult = -1;
|
|
||||||
saCmdPending = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool
|
|
||||||
packageNameMatches(char* clazzName, char* pkg) {
|
|
||||||
int pkgLen = strlen(pkg);
|
|
||||||
int clazzNameLen = strlen(clazzName);
|
|
||||||
|
|
||||||
if (pkgLen >= clazzNameLen + 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(clazzName, pkg, pkgLen)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure that '/' is the next character if non-empty package name
|
|
||||||
int l = pkgLen;
|
|
||||||
if (l > 0) {
|
|
||||||
if (clazzName[l] != '/') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
l++;
|
|
||||||
}
|
|
||||||
// Ensure that there are no more trailing slashes
|
|
||||||
while (l < clazzNameLen) {
|
|
||||||
if (clazzName[l++] == '/') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
executeOneCommand(JNIEnv* env) {
|
|
||||||
switch (saCmdType) {
|
|
||||||
case SA_CMD_SUSPEND_ALL: {
|
|
||||||
if (suspended) {
|
|
||||||
reportErrorToSA("Target process already suspended");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We implement this by getting all of the threads and calling
|
|
||||||
// SuspendThread on each one, except for the thread object
|
|
||||||
// corresponding to this thread. Each thread for which the call
|
|
||||||
// succeeded (i.e., did not return JVMDI_ERROR_INVALID_THREAD)
|
|
||||||
// is added to a list which is remembered for later resumption.
|
|
||||||
// Note that this currently has race conditions since a thread
|
|
||||||
// might be started after we call GetAllThreads and since a
|
|
||||||
// thread for which we got an error earlier might be resumed by
|
|
||||||
// the VM while we are busy suspending other threads. We could
|
|
||||||
// solve this by looping until there are no more threads we can
|
|
||||||
// suspend, but a more robust and scalable solution is to add
|
|
||||||
// this functionality to the JVMDI interface (i.e.,
|
|
||||||
// "suspendAll"). Probably need to provide an exclude list for
|
|
||||||
// such a routine.
|
|
||||||
jint threadCount;
|
|
||||||
jthread* threads;
|
|
||||||
if (jvmdi->GetAllThreads(&threadCount, &threads) != JVMDI_ERROR_NONE) {
|
|
||||||
reportErrorToSA("Error while getting thread list");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < threadCount; i++) {
|
|
||||||
jthread thr = threads[i];
|
|
||||||
if (!env->IsSameObject(thr, debugThreadObj)) {
|
|
||||||
jvmdiError err = jvmdi->SuspendThread(thr);
|
|
||||||
if (err == JVMDI_ERROR_NONE) {
|
|
||||||
// Remember this thread and do not free it
|
|
||||||
suspendedThreads.push_back(thr);
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
fprintf(stderr, " SA: Error %d while suspending thread\n", err);
|
|
||||||
// FIXME: stop, resume all threads, report error
|
|
||||||
}
|
|
||||||
}
|
|
||||||
env->DeleteGlobalRef(thr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free up threads
|
|
||||||
jvmdi->Deallocate((jbyte*) threads);
|
|
||||||
|
|
||||||
// Suspension is complete
|
|
||||||
suspended = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SA_CMD_RESUME_ALL: {
|
|
||||||
if (!suspended) {
|
|
||||||
reportErrorToSA("Target process already suspended");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
saCmdResult = 0;
|
|
||||||
bool errorOccurred = false;
|
|
||||||
jvmdiError firstError;
|
|
||||||
for (int i = 0; i < suspendedThreads.size(); i++) {
|
|
||||||
jthread thr = suspendedThreads[i];
|
|
||||||
jvmdiError err = jvmdi->ResumeThread(thr);
|
|
||||||
env->DeleteGlobalRef(thr);
|
|
||||||
if (err != JVMDI_ERROR_NONE) {
|
|
||||||
if (!errorOccurred) {
|
|
||||||
errorOccurred = true;
|
|
||||||
firstError = err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
suspendedThreads.clear();
|
|
||||||
suspended = false;
|
|
||||||
if (errorOccurred) {
|
|
||||||
reportErrorToSA("Error %d while resuming threads", firstError);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SA_CMD_TOGGLE_BREAKPOINT: {
|
|
||||||
saCmdBkptResWasError = 1;
|
|
||||||
|
|
||||||
// Search line number info for all loaded classes
|
|
||||||
jint classCount;
|
|
||||||
jclass* classes;
|
|
||||||
|
|
||||||
jvmdiError glcRes = jvmdi->GetLoadedClasses(&classCount, &classes);
|
|
||||||
if (glcRes != JVMDI_ERROR_NONE) {
|
|
||||||
reportErrorToSA("Error %d while getting loaded classes", glcRes);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JvmdiRefListDeallocator rld(env, (jobject*) classes, classCount);
|
|
||||||
|
|
||||||
bool done = false;
|
|
||||||
bool gotOne = false;
|
|
||||||
jclass targetClass;
|
|
||||||
jmethodID targetMethod;
|
|
||||||
jlocation targetLocation;
|
|
||||||
jint targetLineNumber;
|
|
||||||
|
|
||||||
for (int i = 0; i < classCount && !done; i++) {
|
|
||||||
fflush(stderr);
|
|
||||||
jclass clazz = classes[i];
|
|
||||||
char* srcName;
|
|
||||||
jvmdiError sfnRes = jvmdi->GetSourceFileName(clazz, &srcName);
|
|
||||||
if (sfnRes == JVMDI_ERROR_NONE) {
|
|
||||||
JvmdiDeallocator de1(srcName);
|
|
||||||
if (!strcmp(srcName, saCmdBkptSrcFileName)) {
|
|
||||||
// Got a match. Now see whether the package name of the class also matches
|
|
||||||
char* clazzName;
|
|
||||||
jvmdiError sigRes = jvmdi->GetClassSignature(clazz, &clazzName);
|
|
||||||
if (sigRes != JVMDI_ERROR_NONE) {
|
|
||||||
reportErrorToSA("Error %d while getting a class's signature", sigRes);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JvmdiDeallocator de2(clazzName);
|
|
||||||
if (packageNameMatches(clazzName + 1, saCmdBkptPkgName)) {
|
|
||||||
// Iterate through all methods
|
|
||||||
jint methodCount;
|
|
||||||
jmethodID* methods;
|
|
||||||
if (jvmdi->GetClassMethods(clazz, &methodCount, &methods) != JVMDI_ERROR_NONE) {
|
|
||||||
reportErrorToSA("Error while getting methods of class %s", clazzName);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
JvmdiDeallocator de3(methods);
|
|
||||||
for (int j = 0; j < methodCount && !done; j++) {
|
|
||||||
jmethodID m = methods[j];
|
|
||||||
jint entryCount;
|
|
||||||
JVMDI_line_number_entry* table;
|
|
||||||
jvmdiError lnRes = jvmdi->GetLineNumberTable(clazz, m, &entryCount, &table);
|
|
||||||
if (lnRes == JVMDI_ERROR_NONE) {
|
|
||||||
JvmdiDeallocator de4(table);
|
|
||||||
// Look for line number greater than or equal to requested line
|
|
||||||
for (int k = 0; k < entryCount && !done; k++) {
|
|
||||||
JVMDI_line_number_entry& entry = table[k];
|
|
||||||
if (entry.line_number >= saCmdBkptLineNumber &&
|
|
||||||
(!gotOne || entry.line_number < targetLineNumber)) {
|
|
||||||
gotOne = true;
|
|
||||||
targetClass = clazz;
|
|
||||||
targetMethod = m;
|
|
||||||
targetLocation = entry.start_location;
|
|
||||||
targetLineNumber = entry.line_number;
|
|
||||||
done = (targetLineNumber == saCmdBkptLineNumber);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (lnRes != JVMDI_ERROR_ABSENT_INFORMATION) {
|
|
||||||
reportErrorToSA("Unexpected error %d while fetching line number table", lnRes);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (sfnRes != JVMDI_ERROR_ABSENT_INFORMATION) {
|
|
||||||
reportErrorToSA("Unexpected error %d while fetching source file name", sfnRes);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wasSet = true;
|
|
||||||
if (gotOne) {
|
|
||||||
// Really toggle this breakpoint
|
|
||||||
jvmdiError bpRes;
|
|
||||||
bpRes = jvmdi->SetBreakpoint(targetClass, targetMethod, targetLocation);
|
|
||||||
if (bpRes == JVMDI_ERROR_DUPLICATE) {
|
|
||||||
bpRes = jvmdi->ClearBreakpoint(targetClass, targetMethod, targetLocation);
|
|
||||||
wasSet = false;
|
|
||||||
}
|
|
||||||
if (bpRes != JVMDI_ERROR_NONE) {
|
|
||||||
reportErrorToSA("Unexpected error %d while setting or clearing breakpoint at bci %d, line %d",
|
|
||||||
bpRes, targetLocation, targetLineNumber);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
saCmdBkptResWasError = 0;
|
|
||||||
reportErrorToSA("No debug information found covering this line");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Provide result
|
|
||||||
saCmdBkptResLineNumber = targetLineNumber;
|
|
||||||
saCmdBkptResBCI = targetLocation;
|
|
||||||
saCmdBkptResWasSet = (wasSet ? 1 : 0);
|
|
||||||
{
|
|
||||||
char* methodName;
|
|
||||||
char* methodSig;
|
|
||||||
if (jvmdi->GetMethodName(targetClass, targetMethod, &methodName, &methodSig)
|
|
||||||
== JVMDI_ERROR_NONE) {
|
|
||||||
JvmdiDeallocator mnd(methodName);
|
|
||||||
JvmdiDeallocator msd(methodSig);
|
|
||||||
strncpy(saCmdBkptResMethodName, methodName, SA_CMD_BUF_SIZE);
|
|
||||||
strncpy(saCmdBkptResMethodSig, methodSig, SA_CMD_BUF_SIZE);
|
|
||||||
} else {
|
|
||||||
strncpy(saCmdBkptResMethodName, "<error>", SA_CMD_BUF_SIZE);
|
|
||||||
strncpy(saCmdBkptResMethodSig, "<error>", SA_CMD_BUF_SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
reportErrorToSA("Command %d not yet supported", saCmdType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Successful command execution
|
|
||||||
saCmdResult = 0;
|
|
||||||
saCmdPending = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
saCommandThread(void *arg) {
|
|
||||||
JNIEnv* env = NULL;
|
|
||||||
if (jvm->GetEnv((void **) &env, JNI_VERSION_1_2) != JNI_OK) {
|
|
||||||
stop("Error while starting Serviceability Agent "
|
|
||||||
"command thread: could not get JNI environment");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
// Wait for command
|
|
||||||
while (!saCmdPending) {
|
|
||||||
SLEEP();
|
|
||||||
}
|
|
||||||
|
|
||||||
executeOneCommand(env);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
saEventHook(JNIEnv *env, JVMDI_Event *event)
|
|
||||||
{
|
|
||||||
MonitorLocker ml(eventLock);
|
|
||||||
|
|
||||||
saEventKind = event->kind;
|
|
||||||
|
|
||||||
if (event->kind == JVMDI_EVENT_VM_INIT) {
|
|
||||||
// Create event lock
|
|
||||||
if (jvmdi->CreateRawMonitor("Serviceability Agent Event Lock", &eventLock)
|
|
||||||
!= JVMDI_ERROR_NONE) {
|
|
||||||
stop("Unable to create Serviceability Agent's event lock");
|
|
||||||
}
|
|
||||||
// Start thread which receives commands from the SA.
|
|
||||||
jclass threadClass = env->FindClass("java/lang/Thread");
|
|
||||||
if (threadClass == NULL) stop("Unable to find class java/lang/Thread");
|
|
||||||
jstring threadName = env->NewStringUTF("Serviceability Agent Command Thread");
|
|
||||||
if (threadName == NULL) stop("Unable to allocate debug thread name");
|
|
||||||
jmethodID ctor = env->GetMethodID(threadClass, "<init>", "(Ljava/lang/String;)V");
|
|
||||||
if (ctor == NULL) stop("Unable to find appropriate constructor for java/lang/Thread");
|
|
||||||
// Allocate thread object
|
|
||||||
jthread thr = (jthread) env->NewObject(threadClass, ctor, threadName);
|
|
||||||
if (thr == NULL) stop("Unable to allocate debug thread's java/lang/Thread instance");
|
|
||||||
// Remember which thread this is
|
|
||||||
debugThreadObj = env->NewGlobalRef(thr);
|
|
||||||
if (debugThreadObj == NULL) stop("Unable to allocate global ref for debug thread object");
|
|
||||||
// Start thread
|
|
||||||
jvmdiError err;
|
|
||||||
if ((err = jvmdi->RunDebugThread(thr, &saCommandThread, NULL, JVMDI_THREAD_NORM_PRIORITY))
|
|
||||||
!= JVMDI_ERROR_NONE) {
|
|
||||||
char buf[256];
|
|
||||||
sprintf(buf, "Error %d while starting debug thread", err);
|
|
||||||
stop(buf);
|
|
||||||
}
|
|
||||||
// OK, initialization is done
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!saAttached) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (event->kind) {
|
|
||||||
case JVMDI_EVENT_EXCEPTION: {
|
|
||||||
fprintf(stderr, "SA: Exception thrown -- ignoring\n");
|
|
||||||
saExceptionThread = event->u.exception.thread;
|
|
||||||
saExceptionClass = event->u.exception.clazz;
|
|
||||||
saExceptionMethod = event->u.exception.method;
|
|
||||||
saExceptionLocation = event->u.exception.location;
|
|
||||||
saExceptionException = event->u.exception.exception;
|
|
||||||
saExceptionCatchClass = event->u.exception.catch_clazz;
|
|
||||||
saExceptionCatchClass = event->u.exception.catch_clazz;
|
|
||||||
saExceptionCatchMethod = event->u.exception.catch_method;
|
|
||||||
saExceptionCatchLocation = event->u.exception.catch_location;
|
|
||||||
// saEventPending = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case JVMDI_EVENT_BREAKPOINT: {
|
|
||||||
saBreakpointThread = event->u.breakpoint.thread;
|
|
||||||
saBreakpointClass = event->u.breakpoint.clazz;
|
|
||||||
saBreakpointMethod = event->u.breakpoint.method;
|
|
||||||
saBreakpointLocation = event->u.breakpoint.location;
|
|
||||||
saEventPending = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (saAttached && saEventPending) {
|
|
||||||
SLEEP();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
JNIEXPORT jint JNICALL
|
|
||||||
JVM_OnLoad(JavaVM *vm, char *options, void *reserved)
|
|
||||||
{
|
|
||||||
jvm = vm;
|
|
||||||
if (jvm->GetEnv((void**) &jvmdi, JVMDI_VERSION_1) != JNI_OK) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (jvmdi->SetEventHook(&saEventHook) != JVMDI_ERROR_NONE) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,105 +0,0 @@
|
|||||||
# Microsoft Developer Studio Project File - Name="sa" - Package Owner=<4>
|
|
||||||
# Microsoft Developer Studio Generated Build File, Format Version 6.00
|
|
||||||
# ** DO NOT EDIT **
|
|
||||||
|
|
||||||
# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
|
|
||||||
|
|
||||||
CFG=sa - Win32 Debug
|
|
||||||
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
|
|
||||||
!MESSAGE use the Export Makefile command and run
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "sa.mak".
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE You can specify a configuration when running NMAKE
|
|
||||||
!MESSAGE by defining the macro CFG on the command line. For example:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE NMAKE /f "sa.mak" CFG="sa - Win32 Debug"
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE Possible choices for configuration are:
|
|
||||||
!MESSAGE
|
|
||||||
!MESSAGE "sa - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE "sa - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
|
|
||||||
!MESSAGE
|
|
||||||
|
|
||||||
# Begin Project
|
|
||||||
# PROP AllowPerConfigDependencies 0
|
|
||||||
# PROP Scc_ProjName ""
|
|
||||||
# PROP Scc_LocalPath ""
|
|
||||||
CPP=cl.exe
|
|
||||||
MTL=midl.exe
|
|
||||||
RSC=rc.exe
|
|
||||||
|
|
||||||
!IF "$(CFG)" == "sa - Win32 Release"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 0
|
|
||||||
# PROP BASE Output_Dir "Release"
|
|
||||||
# PROP BASE Intermediate_Dir "Release"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 0
|
|
||||||
# PROP Output_Dir "Release"
|
|
||||||
# PROP Intermediate_Dir "Release"
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /c
|
|
||||||
# ADD CPP /nologo /MT /W3 /GX /O2 /I "D:\jdk1.4\include" /I "D:\jdk1.4\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /c
|
|
||||||
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "NDEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "NDEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
|
|
||||||
|
|
||||||
!ELSEIF "$(CFG)" == "sa - Win32 Debug"
|
|
||||||
|
|
||||||
# PROP BASE Use_MFC 0
|
|
||||||
# PROP BASE Use_Debug_Libraries 1
|
|
||||||
# PROP BASE Output_Dir "Debug"
|
|
||||||
# PROP BASE Intermediate_Dir "Debug"
|
|
||||||
# PROP BASE Target_Dir ""
|
|
||||||
# PROP Use_MFC 0
|
|
||||||
# PROP Use_Debug_Libraries 1
|
|
||||||
# PROP Output_Dir "Debug"
|
|
||||||
# PROP Intermediate_Dir "Debug"
|
|
||||||
# PROP Target_Dir ""
|
|
||||||
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "D:\jdk1.4\include" /I "D:\jdk1.4\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SA_EXPORTS" /YX /FD /GZ /c
|
|
||||||
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
|
|
||||||
# ADD BASE RSC /l 0x409 /d "_DEBUG"
|
|
||||||
# ADD RSC /l 0x409 /d "_DEBUG"
|
|
||||||
BSC32=bscmake.exe
|
|
||||||
# ADD BASE BSC32 /nologo
|
|
||||||
# ADD BSC32 /nologo
|
|
||||||
LINK32=link.exe
|
|
||||||
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
|
|
||||||
|
|
||||||
!ENDIF
|
|
||||||
|
|
||||||
# Begin Target
|
|
||||||
|
|
||||||
# Name "sa - Win32 Release"
|
|
||||||
# Name "sa - Win32 Debug"
|
|
||||||
# Begin Group "Source Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
|
|
||||||
# Begin Source File
|
|
||||||
|
|
||||||
SOURCE=.\sa.cpp
|
|
||||||
# End Source File
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Header Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "h;hpp;hxx;hm;inl"
|
|
||||||
# End Group
|
|
||||||
# Begin Group "Resource Files"
|
|
||||||
|
|
||||||
# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
|
|
||||||
# End Group
|
|
||||||
# End Target
|
|
||||||
# End Project
|
|
@ -1,29 +0,0 @@
|
|||||||
Microsoft Developer Studio Workspace File, Format Version 6.00
|
|
||||||
# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Project: "sa"=.\sa.dsp - Package Owner=<4>
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<4>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
Global:
|
|
||||||
|
|
||||||
Package=<5>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
Package=<3>
|
|
||||||
{{{
|
|
||||||
}}}
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
|
|
@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "jni.h"
|
|
||||||
|
|
||||||
extern "C" {
|
|
||||||
JNIEXPORT jint JNICALL
|
|
||||||
JVM_OnLoad(JavaVM *vm, char *options, void *reserved);
|
|
||||||
}
|
|
@ -464,9 +464,6 @@ endif
|
|||||||
$(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
|
$(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
|
||||||
$(install-file)
|
$(install-file)
|
||||||
|
|
||||||
$(EXPORT_JRE_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar
|
|
||||||
$(install-file)
|
|
||||||
|
|
||||||
# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h)
|
# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.h, jfr.h)
|
||||||
$(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/%
|
$(EXPORT_INCLUDE_DIR)/%: $(GEN_DIR)/jvmtifiles/%
|
||||||
$(install-file)
|
$(install-file)
|
||||||
|
@ -157,8 +157,6 @@ EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
|
|||||||
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
|
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
|
||||||
EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
|
EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
|
||||||
|
|
||||||
EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
|
|
||||||
|
|
||||||
ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
|
ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
|
||||||
EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
|
EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
|
||||||
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
|
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
|
||||||
|
@ -337,9 +337,6 @@ include $(MAKEFILES_DIR)/jsig.make
|
|||||||
# Serviceability agent
|
# Serviceability agent
|
||||||
include $(MAKEFILES_DIR)/saproc.make
|
include $(MAKEFILES_DIR)/saproc.make
|
||||||
|
|
||||||
# Whitebox testing API
|
|
||||||
include $(MAKEFILES_DIR)/wb.make
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
ifeq ($(OS_VENDOR), Darwin)
|
ifeq ($(OS_VENDOR), Darwin)
|
||||||
@ -347,10 +344,10 @@ $(LIBJVM).dSYM: $(LIBJVM)
|
|||||||
dsymutil $(LIBJVM)
|
dsymutil $(LIBJVM)
|
||||||
|
|
||||||
# no libjvm_db for macosx
|
# no libjvm_db for macosx
|
||||||
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM $(WB_JAR)
|
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(BUILDLIBSAPROC) dtraceCheck $(LIBJVM).dSYM
|
||||||
echo "Doing vm.make build:"
|
echo "Doing vm.make build:"
|
||||||
else
|
else
|
||||||
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) $(WB_JAR)
|
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
install: install_jvm install_jsig install_saproc
|
install: install_jvm install_jsig install_saproc
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
#
|
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License version 2 only, as
|
|
||||||
# published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
# version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
# accompanied this code).
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version
|
|
||||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
# or visit www.oracle.com if you need additional information or have any
|
|
||||||
# questions.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
# Rules to build whitebox testing library, used by vm.make
|
|
||||||
WB = wb
|
|
||||||
|
|
||||||
WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
|
|
||||||
|
|
||||||
WB_JAR = $(GENERATED)/$(WB).jar
|
|
||||||
|
|
||||||
WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
|
|
||||||
WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
|
|
||||||
|
|
||||||
WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
|
|
||||||
$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
|
|
||||||
|
|
||||||
$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
|
|
||||||
$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
|
|
||||||
|
|
||||||
$(WB_JAR): $(WB_JAVA_CLASSES)
|
|
||||||
$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
|
|
||||||
|
|
||||||
$(WB_JAVA_CLASSDIR):
|
|
||||||
$(QUIETLY) mkdir -p $@
|
|
||||||
|
|
@ -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=20
|
HS_BUILD_NUMBER=21
|
||||||
|
|
||||||
JDK_MAJOR_VER=1
|
JDK_MAJOR_VER=1
|
||||||
JDK_MINOR_VER=8
|
JDK_MINOR_VER=8
|
||||||
|
@ -258,8 +258,6 @@ EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
|
|||||||
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
|
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
|
||||||
EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
|
EXPORT_MINIMAL_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/minimal
|
||||||
|
|
||||||
EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
|
|
||||||
|
|
||||||
ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
|
ifeq ($(findstring true, $(JVM_VARIANT_SERVER) $(JVM_VARIANT_ZERO) $(JVM_VARIANT_ZEROSHARK)), true)
|
||||||
EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
|
EXPORT_LIST += $(EXPORT_SERVER_DIR)/Xusage.txt
|
||||||
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
|
EXPORT_LIST += $(EXPORT_SERVER_DIR)/libjvm.$(LIBRARY_SUFFIX)
|
||||||
|
@ -381,12 +381,9 @@ include $(MAKEFILES_DIR)/jsig.make
|
|||||||
# Serviceability agent
|
# Serviceability agent
|
||||||
include $(MAKEFILES_DIR)/saproc.make
|
include $(MAKEFILES_DIR)/saproc.make
|
||||||
|
|
||||||
# Whitebox testing API
|
|
||||||
include $(MAKEFILES_DIR)/wb.make
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR)
|
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(BUILDLIBSAPROC) dtraceCheck
|
||||||
|
|
||||||
install: install_jvm install_jsig install_saproc
|
install: install_jvm install_jsig install_saproc
|
||||||
|
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
#
|
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License version 2 only, as
|
|
||||||
# published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
# version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
# accompanied this code).
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version
|
|
||||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
# or visit www.oracle.com if you need additional information or have any
|
|
||||||
# questions.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
# Rules to build whitebox testing library, used by vm.make
|
|
||||||
WB = wb
|
|
||||||
|
|
||||||
WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
|
|
||||||
|
|
||||||
WB_JAR = $(GENERATED)/$(WB).jar
|
|
||||||
|
|
||||||
WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
|
|
||||||
WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
|
|
||||||
|
|
||||||
WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
|
|
||||||
$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
|
|
||||||
|
|
||||||
$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
|
|
||||||
$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
|
|
||||||
|
|
||||||
$(WB_JAR): $(WB_JAVA_CLASSES)
|
|
||||||
$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
|
|
||||||
|
|
||||||
$(WB_JAVA_CLASSDIR):
|
|
||||||
$(QUIETLY) mkdir -p $@
|
|
||||||
|
|
@ -24,10 +24,7 @@
|
|||||||
|
|
||||||
# This filelist macro is included in platform specific sa.make
|
# This filelist macro is included in platform specific sa.make
|
||||||
# included all packages/*.java. package list can be generated by
|
# included all packages/*.java. package list can be generated by
|
||||||
# $(GAMMADIR)/agent/make/build-pkglist. Then manually removed all
|
# $(GAMMADIR)/agent/make/build-pkglist.
|
||||||
# classes in sun.jvm.hotspot.ui (and subpackages), all ui classes
|
|
||||||
# in sun.jvm.hotspot.bugspot/hotspot and SPARC and x86 disassembler
|
|
||||||
# classes and sun.jvm.hotspot.utilities.soql.
|
|
||||||
|
|
||||||
# define AGENT_DIR before including this file in sa.make
|
# define AGENT_DIR before including this file in sa.make
|
||||||
|
|
||||||
@ -40,8 +37,6 @@ AGENT_FILES = \
|
|||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/asm/sparc/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/*.java \
|
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/bugspot/tree/*.java \
|
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/c1/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/ci/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/code/*.java \
|
||||||
@ -82,7 +77,6 @@ $(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_implementation/shared/*.java \
|
|||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_interface/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/gc_interface/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/interpreter/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/interpreter/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/jdi/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/jdi/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/livejvm/*.java \
|
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/memory/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/memory/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/oops/*.java \
|
||||||
$(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \
|
$(AGENT_SRC_DIR)/sun/jvm/hotspot/opto/*.java \
|
||||||
|
@ -187,8 +187,6 @@ ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
|
|
||||||
|
|
||||||
EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
|
EXPORT_SERVER_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/server
|
||||||
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
|
EXPORT_CLIENT_DIR = $(EXPORT_JRE_LIB_ARCH_DIR)/client
|
||||||
|
|
||||||
|
@ -347,12 +347,9 @@ include $(MAKEFILES_DIR)/jsig.make
|
|||||||
# Serviceability agent
|
# Serviceability agent
|
||||||
include $(MAKEFILES_DIR)/saproc.make
|
include $(MAKEFILES_DIR)/saproc.make
|
||||||
|
|
||||||
# Whitebox testing API
|
|
||||||
include $(MAKEFILES_DIR)/wb.make
|
|
||||||
|
|
||||||
#----------------------------------------------------------------------
|
#----------------------------------------------------------------------
|
||||||
|
|
||||||
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck $(WB_JAR)
|
build: $(LIBJVM) $(LAUNCHER) $(LIBJSIG) $(LIBJVM_DB) $(LIBJVM_DTRACE) $(BUILDLIBSAPROC) dtraceCheck
|
||||||
|
|
||||||
install: install_jvm install_jsig install_saproc
|
install: install_jvm install_jsig install_saproc
|
||||||
|
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
#
|
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License version 2 only, as
|
|
||||||
# published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
# version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
# accompanied this code).
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version
|
|
||||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
# or visit www.oracle.com if you need additional information or have any
|
|
||||||
# questions.
|
|
||||||
#
|
|
||||||
|
|
||||||
# Rules to build whitebox testing library, used by vm.make
|
|
||||||
|
|
||||||
WB = wb
|
|
||||||
|
|
||||||
WBSRCDIR = $(GAMMADIR)/src/share/tools/whitebox
|
|
||||||
|
|
||||||
WB_JAR = $(GENERATED)/$(WB).jar
|
|
||||||
|
|
||||||
WB_JAVA_SRCS = $(shell find $(WBSRCDIR) -name '*.java')
|
|
||||||
WB_JAVA_CLASSDIR = $(GENERATED)/wb/classes
|
|
||||||
|
|
||||||
WB_JAVA_CLASSES = $(patsubst $(WBSRCDIR)/%,$(WB_JAVA_CLASSDIR)/%, \
|
|
||||||
$(patsubst %.java,%.class,$(WB_JAVA_SRCS)))
|
|
||||||
|
|
||||||
$(WB_JAVA_CLASSDIR)/%.class: $(WBSRCDIR)/%.java $(WB_JAVA_CLASSDIR)
|
|
||||||
$(REMOTE) $(COMPILE.JAVAC) -sourcepath $(WBSRCDIR) -nowarn -d $(WB_JAVA_CLASSDIR) $<
|
|
||||||
|
|
||||||
$(WB_JAR): $(WB_JAVA_CLASSES)
|
|
||||||
$(QUIETLY) $(REMOTE) $(RUN.JAR) cf $@ -C $(WB_JAVA_CLASSDIR)/ .
|
|
||||||
|
|
||||||
$(WB_JAVA_CLASSDIR):
|
|
||||||
$(QUIETLY) mkdir -p $@
|
|
||||||
|
|
@ -33,7 +33,7 @@ GENERATED=../generated
|
|||||||
BUILD_PCH_FILE=_build_pch_file.obj
|
BUILD_PCH_FILE=_build_pch_file.obj
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
|
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
|
||||||
|
|
||||||
!include ../local.make
|
!include ../local.make
|
||||||
!include compile.make
|
!include compile.make
|
||||||
@ -72,4 +72,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def
|
|||||||
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/wb.make
|
|
||||||
|
@ -277,8 +277,6 @@ ifeq ($(JVM_VARIANT_CLIENT),true)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
EXPORT_LIST += $(EXPORT_JRE_LIB_DIR)/wb.jar
|
|
||||||
|
|
||||||
ifeq ($(BUILD_WIN_SA), 1)
|
ifeq ($(BUILD_WIN_SA), 1)
|
||||||
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
|
EXPORT_LIST += $(EXPORT_JRE_BIN_DIR)/sawindbg.$(LIBRARY_SUFFIX)
|
||||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||||
|
@ -33,7 +33,7 @@ GENERATED=../generated
|
|||||||
BUILD_PCH_FILE=_build_pch_file.obj
|
BUILD_PCH_FILE=_build_pch_file.obj
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
|
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
|
||||||
|
|
||||||
!include ../local.make
|
!include ../local.make
|
||||||
!include compile.make
|
!include compile.make
|
||||||
@ -71,4 +71,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def
|
|||||||
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/wb.make
|
|
||||||
|
@ -32,7 +32,7 @@ GENERATED=../generated
|
|||||||
BUILD_PCH_FILE=_build_pch_file.obj
|
BUILD_PCH_FILE=_build_pch_file.obj
|
||||||
!endif
|
!endif
|
||||||
|
|
||||||
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA wb
|
default:: $(BUILD_PCH_FILE) $(AOUT) launcher checkAndBuildSA
|
||||||
|
|
||||||
!include ../local.make
|
!include ../local.make
|
||||||
!include compile.make
|
!include compile.make
|
||||||
@ -82,4 +82,3 @@ $(AOUT): $(Res_Files) $(Obj_Files) vm.def
|
|||||||
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
!include $(WorkSpace)/make/windows/makefiles/shared.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
!include $(WorkSpace)/make/windows/makefiles/sa.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
!include $(WorkSpace)/make/windows/makefiles/launcher.make
|
||||||
!include $(WorkSpace)/make/windows/makefiles/wb.make
|
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
#
|
|
||||||
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
#
|
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License version 2 only, as
|
|
||||||
# published by the Free Software Foundation.
|
|
||||||
#
|
|
||||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
# version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
# accompanied this code).
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License version
|
|
||||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
#
|
|
||||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
# or visit www.oracle.com if you need additional information or have any
|
|
||||||
# questions.
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
||||||
# This makefile is used to build the whitebox testing lib
|
|
||||||
# and compile the tests which use it
|
|
||||||
|
|
||||||
!include $(WorkSpace)/make/windows/makefiles/rules.make
|
|
||||||
|
|
||||||
WBSRCDIR = $(WorkSpace)/src/share/tools/whitebox
|
|
||||||
|
|
||||||
# turn GENERATED into a windows path to get sane dependencies
|
|
||||||
WB_CLASSES=$(GENERATED:/=\)\wb\classes
|
|
||||||
WB_JAR=$(GENERATED:/=\)\wb.jar
|
|
||||||
|
|
||||||
# call recursive make to do wildcard expansion
|
|
||||||
.SUFFIXES : .java .class
|
|
||||||
wb_java_srcs: $(WorkSpace)\src\share\tools\whitebox\sun\hotspot\*.java $(WB_CLASSES)
|
|
||||||
$(MAKE) -f $(WorkSpace)\make\windows\makefiles\$(BUILD_FLAVOR).make $(**:.java=.class)
|
|
||||||
|
|
||||||
|
|
||||||
{$(WorkSpace)\src\share\tools\whitebox\sun\hotspot}.java.class::
|
|
||||||
$(COMPILE_JAVAC) -sourcepath $(WBSRCDIR) -d $(WB_CLASSES) $<
|
|
||||||
|
|
||||||
$(WB_JAR): wb_java_srcs
|
|
||||||
$(RUN_JAR) cf $@ -C $(WB_CLASSES) .
|
|
||||||
|
|
||||||
# turn $@ to a unix path because mkdir in PATH is cygwin/mks mkdir
|
|
||||||
$(WB_CLASSES):
|
|
||||||
mkdir -p $(@:\=/)
|
|
||||||
|
|
||||||
# main target to build wb
|
|
||||||
wb: $(WB_JAR)
|
|
||||||
|
|
@ -216,6 +216,11 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Could just be some random pointer within the codeBlob
|
||||||
|
if (!_cb->code_contains(_pc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Entry frame checks
|
// Entry frame checks
|
||||||
if (is_entry_frame()) {
|
if (is_entry_frame()) {
|
||||||
// an entry frame must have a valid fp.
|
// an entry frame must have a valid fp.
|
||||||
|
@ -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
|
||||||
@ -340,8 +340,6 @@ void TemplateTable::ldc(bool wide) {
|
|||||||
|
|
||||||
__ bind(notInt);
|
__ bind(notInt);
|
||||||
// __ cmp(O2, JVM_CONSTANT_String);
|
// __ cmp(O2, JVM_CONSTANT_String);
|
||||||
__ brx(Assembler::equal, true, Assembler::pt, isString);
|
|
||||||
__ delayed()->cmp(O2, JVM_CONSTANT_Object);
|
|
||||||
__ brx(Assembler::notEqual, true, Assembler::pt, notString);
|
__ brx(Assembler::notEqual, true, Assembler::pt, notString);
|
||||||
__ delayed()->ldf(FloatRegisterImpl::S, O0, O1, Ftos_f);
|
__ delayed()->ldf(FloatRegisterImpl::S, O0, O1, Ftos_f);
|
||||||
__ bind(isString);
|
__ bind(isString);
|
||||||
|
@ -91,6 +91,12 @@ bool frame::safe_for_sender(JavaThread *thread) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Could just be some random pointer within the codeBlob
|
||||||
|
if (!_cb->code_contains(_pc)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Entry frame checks
|
// Entry frame checks
|
||||||
if (is_entry_frame()) {
|
if (is_entry_frame()) {
|
||||||
// an entry frame must have a valid fp.
|
// an entry frame must have a valid fp.
|
||||||
|
@ -4743,49 +4743,26 @@ jlong os::thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
|
|||||||
//
|
//
|
||||||
|
|
||||||
static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
|
static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
|
||||||
static bool proc_pid_cpu_avail = true;
|
|
||||||
static bool proc_task_unchecked = true;
|
static bool proc_task_unchecked = true;
|
||||||
static const char *proc_stat_path = "/proc/%d/stat";
|
static const char *proc_stat_path = "/proc/%d/stat";
|
||||||
pid_t tid = thread->osthread()->thread_id();
|
pid_t tid = thread->osthread()->thread_id();
|
||||||
int i;
|
|
||||||
char *s;
|
char *s;
|
||||||
char stat[2048];
|
char stat[2048];
|
||||||
int statlen;
|
int statlen;
|
||||||
char proc_name[64];
|
char proc_name[64];
|
||||||
int count;
|
int count;
|
||||||
long sys_time, user_time;
|
long sys_time, user_time;
|
||||||
char string[64];
|
|
||||||
char cdummy;
|
char cdummy;
|
||||||
int idummy;
|
int idummy;
|
||||||
long ldummy;
|
long ldummy;
|
||||||
FILE *fp;
|
FILE *fp;
|
||||||
|
|
||||||
// We first try accessing /proc/<pid>/cpu since this is faster to
|
|
||||||
// process. If this file is not present (linux kernels 2.5 and above)
|
|
||||||
// then we open /proc/<pid>/stat.
|
|
||||||
if ( proc_pid_cpu_avail ) {
|
|
||||||
sprintf(proc_name, "/proc/%d/cpu", tid);
|
|
||||||
fp = fopen(proc_name, "r");
|
|
||||||
if ( fp != NULL ) {
|
|
||||||
count = fscanf( fp, "%s %lu %lu\n", string, &user_time, &sys_time);
|
|
||||||
fclose(fp);
|
|
||||||
if ( count != 3 ) return -1;
|
|
||||||
|
|
||||||
if (user_sys_cpu_time) {
|
|
||||||
return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec);
|
|
||||||
} else {
|
|
||||||
return (jlong)user_time * (1000000000 / clock_tics_per_sec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else proc_pid_cpu_avail = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The /proc/<tid>/stat aggregates per-process usage on
|
// The /proc/<tid>/stat aggregates per-process usage on
|
||||||
// new Linux kernels 2.6+ where NPTL is supported.
|
// new Linux kernels 2.6+ where NPTL is supported.
|
||||||
// The /proc/self/task/<tid>/stat still has the per-thread usage.
|
// The /proc/self/task/<tid>/stat still has the per-thread usage.
|
||||||
// See bug 6328462.
|
// See bug 6328462.
|
||||||
// There can be no directory /proc/self/task on kernels 2.4 with NPTL
|
// There possibly can be cases where there is no directory
|
||||||
// and possibly in some other cases, so we check its availability.
|
// /proc/self/task, so we check its availability.
|
||||||
if (proc_task_unchecked && os::Linux::is_NPTL()) {
|
if (proc_task_unchecked && os::Linux::is_NPTL()) {
|
||||||
// This is executed only once
|
// This is executed only once
|
||||||
proc_task_unchecked = false;
|
proc_task_unchecked = false;
|
||||||
@ -4810,7 +4787,6 @@ static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) {
|
|||||||
// We don't really need to know the command string, just find the last
|
// We don't really need to know the command string, just find the last
|
||||||
// occurrence of ")" and then start parsing from there. See bug 4726580.
|
// occurrence of ")" and then start parsing from there. See bug 4726580.
|
||||||
s = strrchr(stat, ')');
|
s = strrchr(stat, ')');
|
||||||
i = 0;
|
|
||||||
if (s == NULL ) return -1;
|
if (s == NULL ) return -1;
|
||||||
|
|
||||||
// Skip blank chars
|
// Skip blank chars
|
||||||
|
@ -1,43 +0,0 @@
|
|||||||
package sun.hotspot.parser;
|
|
||||||
|
|
||||||
public class DiagnosticCommand {
|
|
||||||
|
|
||||||
public enum DiagnosticArgumentType {
|
|
||||||
JLONG, BOOLEAN, STRING, NANOTIME, STRINGARRAY, MEMORYSIZE
|
|
||||||
}
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
private String desc;
|
|
||||||
private DiagnosticArgumentType type;
|
|
||||||
private boolean mandatory;
|
|
||||||
private String defaultValue;
|
|
||||||
|
|
||||||
public DiagnosticCommand(String name, String desc, DiagnosticArgumentType type,
|
|
||||||
boolean mandatory, String defaultValue) {
|
|
||||||
this.name = name;
|
|
||||||
this.desc = desc;
|
|
||||||
this.type = type;
|
|
||||||
this.mandatory = mandatory;
|
|
||||||
this.defaultValue = defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDesc() {
|
|
||||||
return desc;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiagnosticArgumentType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isMandatory() {
|
|
||||||
return mandatory;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDefaultValue() {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
@ -753,10 +753,11 @@ bool InstructForm::captures_bottom_type(FormDict &globals) const {
|
|||||||
!strcmp(_matrule->_rChild->_opType,"DecodeNKlass") ||
|
!strcmp(_matrule->_rChild->_opType,"DecodeNKlass") ||
|
||||||
!strcmp(_matrule->_rChild->_opType,"EncodePKlass") ||
|
!strcmp(_matrule->_rChild->_opType,"EncodePKlass") ||
|
||||||
!strcmp(_matrule->_rChild->_opType,"LoadN") ||
|
!strcmp(_matrule->_rChild->_opType,"LoadN") ||
|
||||||
!strcmp(_matrule->_rChild->_opType,"GetAndSetN") ||
|
|
||||||
!strcmp(_matrule->_rChild->_opType,"LoadNKlass") ||
|
!strcmp(_matrule->_rChild->_opType,"LoadNKlass") ||
|
||||||
!strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception
|
!strcmp(_matrule->_rChild->_opType,"CreateEx") || // type of exception
|
||||||
!strcmp(_matrule->_rChild->_opType,"CheckCastPP")) ) return true;
|
!strcmp(_matrule->_rChild->_opType,"CheckCastPP") ||
|
||||||
|
!strcmp(_matrule->_rChild->_opType,"GetAndSetP") ||
|
||||||
|
!strcmp(_matrule->_rChild->_opType,"GetAndSetN")) ) return true;
|
||||||
else if ( is_ideal_load() == Form::idealP ) return true;
|
else if ( is_ideal_load() == Form::idealP ) return true;
|
||||||
else if ( is_ideal_store() != Form::none ) return true;
|
else if ( is_ideal_store() != Form::none ) return true;
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1999, 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
|
||||||
@ -597,10 +597,6 @@ ciConstant ciEnv::get_constant_by_index_impl(constantPoolHandle cpool,
|
|||||||
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
assert (klass->is_instance_klass() || klass->is_array_klass(),
|
||||||
"must be an instance or array klass ");
|
"must be an instance or array klass ");
|
||||||
return ciConstant(T_OBJECT, klass->java_mirror());
|
return ciConstant(T_OBJECT, klass->java_mirror());
|
||||||
} else if (tag.is_object()) {
|
|
||||||
oop obj = cpool->object_at(index);
|
|
||||||
ciObject* ciobj = get_object(obj);
|
|
||||||
return ciConstant(T_OBJECT, ciobj);
|
|
||||||
} else if (tag.is_method_type()) {
|
} else if (tag.is_method_type()) {
|
||||||
// must execute Java code to link this CP entry into cache[i].f1
|
// must execute Java code to link this CP entry into cache[i].f1
|
||||||
ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index));
|
ciSymbol* signature = get_symbol(cpool->method_type_signature_at(index));
|
||||||
|
@ -117,7 +117,7 @@ void ConcurrentMarkThread::run() {
|
|||||||
if (G1Log::fine()) {
|
if (G1Log::fine()) {
|
||||||
gclog_or_tty->date_stamp(PrintGCDateStamps);
|
gclog_or_tty->date_stamp(PrintGCDateStamps);
|
||||||
gclog_or_tty->stamp(PrintGCTimeStamps);
|
gclog_or_tty->stamp(PrintGCTimeStamps);
|
||||||
gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf]",
|
gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]",
|
||||||
scan_end - scan_start);
|
scan_end - scan_start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,7 +150,7 @@ void ConcurrentMarkThread::run() {
|
|||||||
if (G1Log::fine()) {
|
if (G1Log::fine()) {
|
||||||
gclog_or_tty->date_stamp(PrintGCDateStamps);
|
gclog_or_tty->date_stamp(PrintGCDateStamps);
|
||||||
gclog_or_tty->stamp(PrintGCTimeStamps);
|
gclog_or_tty->stamp(PrintGCTimeStamps);
|
||||||
gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf sec]",
|
gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]",
|
||||||
mark_end_sec - mark_start_sec);
|
mark_end_sec - mark_start_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +234,7 @@ void ConcurrentMarkThread::run() {
|
|||||||
if (G1Log::fine()) {
|
if (G1Log::fine()) {
|
||||||
gclog_or_tty->date_stamp(PrintGCDateStamps);
|
gclog_or_tty->date_stamp(PrintGCDateStamps);
|
||||||
gclog_or_tty->stamp(PrintGCTimeStamps);
|
gclog_or_tty->stamp(PrintGCTimeStamps);
|
||||||
gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf]",
|
gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]",
|
||||||
cleanup_end_sec - cleanup_start_sec);
|
cleanup_end_sec - cleanup_start_sec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,7 +267,15 @@ G1CollectorPolicy::G1CollectorPolicy() :
|
|||||||
double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
|
double max_gc_time = (double) MaxGCPauseMillis / 1000.0;
|
||||||
double time_slice = (double) GCPauseIntervalMillis / 1000.0;
|
double time_slice = (double) GCPauseIntervalMillis / 1000.0;
|
||||||
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
|
_mmu_tracker = new G1MMUTrackerQueue(time_slice, max_gc_time);
|
||||||
_sigma = (double) G1ConfidencePercent / 100.0;
|
|
||||||
|
uintx confidence_perc = G1ConfidencePercent;
|
||||||
|
// Put an artificial ceiling on this so that it's not set to a silly value.
|
||||||
|
if (confidence_perc > 100) {
|
||||||
|
confidence_perc = 100;
|
||||||
|
warning("G1ConfidencePercent is set to a value that is too large, "
|
||||||
|
"it's been updated to %u", confidence_perc);
|
||||||
|
}
|
||||||
|
_sigma = (double) confidence_perc / 100.0;
|
||||||
|
|
||||||
// start conservatively (around 50ms is about right)
|
// start conservatively (around 50ms is about right)
|
||||||
_concurrent_mark_remark_times_ms->add(0.05);
|
_concurrent_mark_remark_times_ms->add(0.05);
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw) \
|
#define G1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, experimental, notproduct, manageable, product_rw) \
|
||||||
\
|
\
|
||||||
product(intx, G1ConfidencePercent, 50, \
|
product(uintx, G1ConfidencePercent, 50, \
|
||||||
"Confidence level for MMU/pause predictions") \
|
"Confidence level for MMU/pause predictions") \
|
||||||
\
|
\
|
||||||
develop(intx, G1MarkingOverheadPercent, 0, \
|
develop(intx, G1MarkingOverheadPercent, 0, \
|
||||||
|
@ -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
|
||||||
@ -335,9 +335,6 @@ void BytecodePrinter::print_constant(int i, outputStream* st) {
|
|||||||
st->print_cr(" %s", constants->resolved_klass_at(i)->external_name());
|
st->print_cr(" %s", constants->resolved_klass_at(i)->external_name());
|
||||||
} else if (tag.is_unresolved_klass()) {
|
} else if (tag.is_unresolved_klass()) {
|
||||||
st->print_cr(" <unresolved klass at %d>", i);
|
st->print_cr(" <unresolved klass at %d>", i);
|
||||||
} else if (tag.is_object()) {
|
|
||||||
st->print(" <Object>");
|
|
||||||
print_oop(constants->object_at(i), st);
|
|
||||||
} else if (tag.is_method_type()) {
|
} else if (tag.is_method_type()) {
|
||||||
int i2 = constants->method_type_index_at(i);
|
int i2 = constants->method_type_index_at(i);
|
||||||
st->print(" <MethodType> %d", i2);
|
st->print(" <MethodType> %d", i2);
|
||||||
|
@ -1241,7 +1241,6 @@ void LinkResolver::resolve_handle_call(CallInfo& result, KlassHandle resolved_kl
|
|||||||
|
|
||||||
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
|
void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle pool, int index, TRAPS) {
|
||||||
assert(EnableInvokeDynamic, "");
|
assert(EnableInvokeDynamic, "");
|
||||||
pool->set_has_invokedynamic(); // mark header to flag active call sites
|
|
||||||
|
|
||||||
//resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
|
//resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
|
||||||
Symbol* method_name = pool->name_ref_at(index);
|
Symbol* method_name = pool->name_ref_at(index);
|
||||||
|
@ -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
|
||||||
@ -48,7 +48,6 @@ void Rewriter::compute_index_maps() {
|
|||||||
add_cp_cache_entry(i);
|
add_cp_cache_entry(i);
|
||||||
break;
|
break;
|
||||||
case JVM_CONSTANT_String:
|
case JVM_CONSTANT_String:
|
||||||
case JVM_CONSTANT_Object:
|
|
||||||
case JVM_CONSTANT_MethodHandle : // fall through
|
case JVM_CONSTANT_MethodHandle : // fall through
|
||||||
case JVM_CONSTANT_MethodType : // fall through
|
case JVM_CONSTANT_MethodType : // fall through
|
||||||
add_resolved_references_entry(i);
|
add_resolved_references_entry(i);
|
||||||
@ -238,7 +237,7 @@ void Rewriter::maybe_rewrite_ldc(address bcp, int offset, bool is_wide,
|
|||||||
address p = bcp + offset;
|
address p = bcp + offset;
|
||||||
int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
|
int cp_index = is_wide ? Bytes::get_Java_u2(p) : (u1)(*p);
|
||||||
constantTag tag = _pool->tag_at(cp_index).value();
|
constantTag tag = _pool->tag_at(cp_index).value();
|
||||||
if (tag.is_method_handle() || tag.is_method_type() || tag.is_string() || tag.is_object()) {
|
if (tag.is_method_handle() || tag.is_method_type() || tag.is_string()) {
|
||||||
int ref_index = cp_entry_to_resolved_references(cp_index);
|
int ref_index = cp_entry_to_resolved_references(cp_index);
|
||||||
if (is_wide) {
|
if (is_wide) {
|
||||||
(*bcp) = Bytecodes::_fast_aldc_w;
|
(*bcp) = Bytecodes::_fast_aldc_w;
|
||||||
|
@ -695,10 +695,6 @@ oop ConstantPool::resolve_constant_at_impl(constantPoolHandle this_oop, int inde
|
|||||||
result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL);
|
result_oop = string_at_impl(this_oop, index, cache_index, CHECK_NULL);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case JVM_CONSTANT_Object:
|
|
||||||
result_oop = this_oop->object_at(index);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case JVM_CONSTANT_MethodHandleInError:
|
case JVM_CONSTANT_MethodHandleInError:
|
||||||
case JVM_CONSTANT_MethodTypeInError:
|
case JVM_CONSTANT_MethodTypeInError:
|
||||||
{
|
{
|
||||||
@ -1824,8 +1820,6 @@ void ConstantPool::print_on(outputStream* st) const {
|
|||||||
st->print_cr(internal_name());
|
st->print_cr(internal_name());
|
||||||
if (flags() != 0) {
|
if (flags() != 0) {
|
||||||
st->print(" - flags: 0x%x", flags());
|
st->print(" - flags: 0x%x", flags());
|
||||||
if (has_pseudo_string()) st->print(" has_pseudo_string");
|
|
||||||
if (has_invokedynamic()) st->print(" has_invokedynamic");
|
|
||||||
if (has_preresolution()) st->print(" has_preresolution");
|
if (has_preresolution()) st->print(" has_preresolution");
|
||||||
if (on_stack()) st->print(" on_stack");
|
if (on_stack()) st->print(" on_stack");
|
||||||
st->cr();
|
st->cr();
|
||||||
@ -1869,13 +1863,14 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) {
|
|||||||
st->print(" name_and_type_index=%d", uncached_name_and_type_ref_index_at(index));
|
st->print(" name_and_type_index=%d", uncached_name_and_type_ref_index_at(index));
|
||||||
break;
|
break;
|
||||||
case JVM_CONSTANT_String :
|
case JVM_CONSTANT_String :
|
||||||
unresolved_string_at(index)->print_value_on(st);
|
if (is_pseudo_string_at(index)) {
|
||||||
|
oop anObj = pseudo_string_at(index);
|
||||||
|
anObj->print_value_on(st);
|
||||||
|
st->print(" {0x%lx}", (address)anObj);
|
||||||
|
} else {
|
||||||
|
unresolved_string_at(index)->print_value_on(st);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case JVM_CONSTANT_Object : {
|
|
||||||
oop anObj = object_at(index);
|
|
||||||
anObj->print_value_on(st);
|
|
||||||
st->print(" {0x%lx}", (address)anObj);
|
|
||||||
} break;
|
|
||||||
case JVM_CONSTANT_Integer :
|
case JVM_CONSTANT_Integer :
|
||||||
st->print("%d", int_at(index));
|
st->print("%d", int_at(index));
|
||||||
break;
|
break;
|
||||||
@ -1939,8 +1934,6 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) {
|
|||||||
void ConstantPool::print_value_on(outputStream* st) const {
|
void ConstantPool::print_value_on(outputStream* st) const {
|
||||||
assert(is_constantPool(), "must be constantPool");
|
assert(is_constantPool(), "must be constantPool");
|
||||||
st->print("constant pool [%d]", length());
|
st->print("constant pool [%d]", length());
|
||||||
if (has_pseudo_string()) st->print("/pseudo_string");
|
|
||||||
if (has_invokedynamic()) st->print("/invokedynamic");
|
|
||||||
if (has_preresolution()) st->print("/preresolution");
|
if (has_preresolution()) st->print("/preresolution");
|
||||||
if (operands() != NULL) st->print("/operands[%d]", operands()->length());
|
if (operands() != NULL) st->print("/operands[%d]", operands()->length());
|
||||||
print_address_on(st);
|
print_address_on(st);
|
||||||
|
@ -97,10 +97,8 @@ class ConstantPool : public Metadata {
|
|||||||
Array<u2>* _reference_map;
|
Array<u2>* _reference_map;
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
_has_invokedynamic = 1, // Flags
|
_has_preresolution = 1, // Flags
|
||||||
_has_pseudo_string = 2,
|
_on_stack = 2
|
||||||
_has_preresolution = 4,
|
|
||||||
_on_stack = 8
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int _flags; // old fashioned bit twiddling
|
int _flags; // old fashioned bit twiddling
|
||||||
@ -175,12 +173,6 @@ class ConstantPool : public Metadata {
|
|||||||
Array<u1>* tags() const { return _tags; }
|
Array<u1>* tags() const { return _tags; }
|
||||||
Array<u2>* operands() const { return _operands; }
|
Array<u2>* operands() const { return _operands; }
|
||||||
|
|
||||||
bool has_invokedynamic() const { return (_flags & _has_invokedynamic) != 0; }
|
|
||||||
void set_has_invokedynamic() { _flags |= _has_invokedynamic; }
|
|
||||||
|
|
||||||
bool has_pseudo_string() const { return (_flags & _has_pseudo_string) != 0; }
|
|
||||||
void set_has_pseudo_string() { _flags |= _has_pseudo_string; }
|
|
||||||
|
|
||||||
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; }
|
bool has_preresolution() const { return (_flags & _has_preresolution) != 0; }
|
||||||
void set_has_preresolution() { _flags |= _has_preresolution; }
|
void set_has_preresolution() { _flags |= _has_preresolution; }
|
||||||
|
|
||||||
@ -324,14 +316,6 @@ class ConstantPool : public Metadata {
|
|||||||
resolved_references()->obj_at_put(obj_index, str);
|
resolved_references()->obj_at_put(obj_index, str);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_object_tag_at(int which) {
|
|
||||||
release_tag_at_put(which, JVM_CONSTANT_Object);
|
|
||||||
}
|
|
||||||
|
|
||||||
void object_at_put(int which, oop obj) {
|
|
||||||
resolved_references()->obj_at_put(cp_to_object_index(which), obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
// For temporary use while constructing constant pool
|
// For temporary use while constructing constant pool
|
||||||
void string_index_at_put(int which, int string_index) {
|
void string_index_at_put(int which, int string_index) {
|
||||||
tag_at_put(which, JVM_CONSTANT_StringIndex);
|
tag_at_put(which, JVM_CONSTANT_StringIndex);
|
||||||
@ -429,12 +413,6 @@ class ConstantPool : public Metadata {
|
|||||||
// Version that can be used before string oop array is created.
|
// Version that can be used before string oop array is created.
|
||||||
oop uncached_string_at(int which, TRAPS);
|
oop uncached_string_at(int which, TRAPS);
|
||||||
|
|
||||||
oop object_at(int which) {
|
|
||||||
assert(tag_at(which).is_object(), "Corrupted constant pool");
|
|
||||||
int obj_index = cp_to_object_index(which);
|
|
||||||
return resolved_references()->obj_at(obj_index);
|
|
||||||
}
|
|
||||||
|
|
||||||
// A "pseudo-string" is an non-string oop that has found is way into
|
// A "pseudo-string" is an non-string oop that has found is way into
|
||||||
// a String entry.
|
// a String entry.
|
||||||
// Under EnableInvokeDynamic this can happen if the user patches a live
|
// Under EnableInvokeDynamic this can happen if the user patches a live
|
||||||
@ -454,10 +432,18 @@ class ConstantPool : public Metadata {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
oop pseudo_string_at(int which) {
|
||||||
|
assert(tag_at(which).is_string(), "Corrupted constant pool");
|
||||||
|
assert(unresolved_string_at(which) == NULL, "shouldn't have symbol");
|
||||||
|
int obj_index = cp_to_object_index(which);
|
||||||
|
oop s = resolved_references()->obj_at(obj_index);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
void pseudo_string_at_put(int which, int obj_index, oop x) {
|
void pseudo_string_at_put(int which, int obj_index, oop x) {
|
||||||
assert(EnableInvokeDynamic, "");
|
assert(EnableInvokeDynamic, "");
|
||||||
set_has_pseudo_string(); // mark header
|
|
||||||
assert(tag_at(which).is_string(), "Corrupted constant pool");
|
assert(tag_at(which).is_string(), "Corrupted constant pool");
|
||||||
|
unresolved_string_at_put(which, NULL); // indicates patched string
|
||||||
string_at_put(which, obj_index, x); // this works just fine
|
string_at_put(which, obj_index, x); // this works just fine
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
@ -1853,7 +1853,6 @@ void GenerateOopMap::do_ldc(int bci) {
|
|||||||
if (tag.is_klass() ||
|
if (tag.is_klass() ||
|
||||||
tag.is_unresolved_klass() ||
|
tag.is_unresolved_klass() ||
|
||||||
tag.is_string() ||
|
tag.is_string() ||
|
||||||
tag.is_object() ||
|
|
||||||
tag.is_method_handle() ||
|
tag.is_method_handle() ||
|
||||||
tag.is_method_type()) {
|
tag.is_method_type()) {
|
||||||
assert(bt == T_OBJECT, "Guard is incorrect");
|
assert(bt == T_OBJECT, "Guard is incorrect");
|
||||||
|
@ -47,7 +47,8 @@ InlineTree::InlineTree(Compile* c,
|
|||||||
_site_invoke_ratio(site_invoke_ratio),
|
_site_invoke_ratio(site_invoke_ratio),
|
||||||
_max_inline_level(max_inline_level),
|
_max_inline_level(max_inline_level),
|
||||||
_count_inline_bcs(method()->code_size_for_inlining()),
|
_count_inline_bcs(method()->code_size_for_inlining()),
|
||||||
_subtrees(c->comp_arena(), 2, 0, NULL)
|
_subtrees(c->comp_arena(), 2, 0, NULL),
|
||||||
|
_msg(NULL)
|
||||||
{
|
{
|
||||||
NOT_PRODUCT(_count_inlines = 0;)
|
NOT_PRODUCT(_count_inlines = 0;)
|
||||||
if (_caller_jvms != NULL) {
|
if (_caller_jvms != NULL) {
|
||||||
@ -77,7 +78,8 @@ InlineTree::InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvm
|
|||||||
_method(callee_method),
|
_method(callee_method),
|
||||||
_site_invoke_ratio(site_invoke_ratio),
|
_site_invoke_ratio(site_invoke_ratio),
|
||||||
_max_inline_level(max_inline_level),
|
_max_inline_level(max_inline_level),
|
||||||
_count_inline_bcs(method()->code_size())
|
_count_inline_bcs(method()->code_size()),
|
||||||
|
_msg(NULL)
|
||||||
{
|
{
|
||||||
NOT_PRODUCT(_count_inlines = 0;)
|
NOT_PRODUCT(_count_inlines = 0;)
|
||||||
assert(!UseOldInlining, "do not use for old stuff");
|
assert(!UseOldInlining, "do not use for old stuff");
|
||||||
@ -95,8 +97,10 @@ static bool is_init_with_ea(ciMethod* callee_method,
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// positive filter: should callee be inlined? returns NULL, if yes, or rejection msg
|
// positive filter: should callee be inlined?
|
||||||
const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const {
|
bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method,
|
||||||
|
int caller_bci, ciCallProfile& profile,
|
||||||
|
WarmCallInfo* wci_result) {
|
||||||
// Allows targeted inlining
|
// Allows targeted inlining
|
||||||
if(callee_method->should_inline()) {
|
if(callee_method->should_inline()) {
|
||||||
*wci_result = *(WarmCallInfo::always_hot());
|
*wci_result = *(WarmCallInfo::always_hot());
|
||||||
@ -104,11 +108,10 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_
|
|||||||
CompileTask::print_inline_indent(inline_level());
|
CompileTask::print_inline_indent(inline_level());
|
||||||
tty->print_cr("Inlined method is hot: ");
|
tty->print_cr("Inlined method is hot: ");
|
||||||
}
|
}
|
||||||
return NULL;
|
set_msg("force inline by CompilerOracle");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// positive filter: should send be inlined? returns NULL (--> yes)
|
|
||||||
// or rejection msg
|
|
||||||
int size = callee_method->code_size_for_inlining();
|
int size = callee_method->code_size_for_inlining();
|
||||||
|
|
||||||
// Check for too many throws (and not too huge)
|
// Check for too many throws (and not too huge)
|
||||||
@ -119,11 +122,13 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_
|
|||||||
CompileTask::print_inline_indent(inline_level());
|
CompileTask::print_inline_indent(inline_level());
|
||||||
tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count());
|
tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count());
|
||||||
}
|
}
|
||||||
return NULL;
|
set_msg("many throws");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UseOldInlining) {
|
if (!UseOldInlining) {
|
||||||
return NULL; // size and frequency are represented in a new way
|
set_msg("!UseOldInlining");
|
||||||
|
return true; // size and frequency are represented in a new way
|
||||||
}
|
}
|
||||||
|
|
||||||
int default_max_inline_size = C->max_inline_size();
|
int default_max_inline_size = C->max_inline_size();
|
||||||
@ -153,31 +158,44 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_
|
|||||||
// Not hot. Check for medium-sized pre-existing nmethod at cold sites.
|
// Not hot. Check for medium-sized pre-existing nmethod at cold sites.
|
||||||
if (callee_method->has_compiled_code() &&
|
if (callee_method->has_compiled_code() &&
|
||||||
callee_method->instructions_size() > inline_small_code_size)
|
callee_method->instructions_size() > inline_small_code_size)
|
||||||
return "already compiled into a medium method";
|
set_msg("already compiled into a medium method");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (size > max_inline_size) {
|
if (size > max_inline_size) {
|
||||||
if (max_inline_size > default_max_inline_size)
|
if (max_inline_size > default_max_inline_size) {
|
||||||
return "hot method too big";
|
set_msg("hot method too big");
|
||||||
return "too big";
|
} else {
|
||||||
|
set_msg("too big");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return NULL;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg
|
// negative filter: should callee NOT be inlined?
|
||||||
const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const {
|
bool InlineTree::should_not_inline(ciMethod *callee_method,
|
||||||
// negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg
|
ciMethod* caller_method,
|
||||||
if (!UseOldInlining) {
|
WarmCallInfo* wci_result) {
|
||||||
const char* fail = NULL;
|
|
||||||
if ( callee_method->is_abstract()) fail = "abstract method";
|
|
||||||
// note: we allow ik->is_abstract()
|
|
||||||
if (!callee_method->holder()->is_initialized()) fail = "method holder not initialized";
|
|
||||||
if ( callee_method->is_native()) fail = "native method";
|
|
||||||
if ( callee_method->dont_inline()) fail = "don't inline by annotation";
|
|
||||||
|
|
||||||
if (fail) {
|
const char* fail_msg = NULL;
|
||||||
|
|
||||||
|
// First check all inlining restrictions which are required for correctness
|
||||||
|
if ( callee_method->is_abstract()) {
|
||||||
|
fail_msg = "abstract method"; // // note: we allow ik->is_abstract()
|
||||||
|
} else if (!callee_method->holder()->is_initialized()) {
|
||||||
|
fail_msg = "method holder not initialized";
|
||||||
|
} else if ( callee_method->is_native()) {
|
||||||
|
fail_msg = "native method";
|
||||||
|
} else if ( callee_method->dont_inline()) {
|
||||||
|
fail_msg = "don't inline by annotation";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!UseOldInlining) {
|
||||||
|
if (fail_msg != NULL) {
|
||||||
*wci_result = *(WarmCallInfo::always_cold());
|
*wci_result = *(WarmCallInfo::always_cold());
|
||||||
return fail;
|
set_msg(fail_msg);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callee_method->has_unloaded_classes_in_signature()) {
|
if (callee_method->has_unloaded_classes_in_signature()) {
|
||||||
@ -199,20 +217,23 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
|
|||||||
// %%% adjust wci_result->size()?
|
// %%% adjust wci_result->size()?
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// First check all inlining restrictions which are required for correctness
|
// one more inlining restriction
|
||||||
if ( callee_method->is_abstract()) return "abstract method";
|
if (fail_msg == NULL && callee_method->has_unloaded_classes_in_signature()) {
|
||||||
// note: we allow ik->is_abstract()
|
fail_msg = "unloaded signature classes";
|
||||||
if (!callee_method->holder()->is_initialized()) return "method holder not initialized";
|
}
|
||||||
if ( callee_method->is_native()) return "native method";
|
|
||||||
if ( callee_method->dont_inline()) return "don't inline by annotation";
|
|
||||||
if ( callee_method->has_unloaded_classes_in_signature()) return "unloaded signature classes";
|
|
||||||
|
|
||||||
|
if (fail_msg != NULL) {
|
||||||
|
set_msg(fail_msg);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore heuristic controls on inlining
|
||||||
if (callee_method->should_inline()) {
|
if (callee_method->should_inline()) {
|
||||||
// ignore heuristic controls on inlining
|
set_msg("force inline by CompilerOracle");
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now perform checks which are heuristic
|
// Now perform checks which are heuristic
|
||||||
@ -220,7 +241,8 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
|
|||||||
if (!callee_method->force_inline()) {
|
if (!callee_method->force_inline()) {
|
||||||
if (callee_method->has_compiled_code() &&
|
if (callee_method->has_compiled_code() &&
|
||||||
callee_method->instructions_size() > InlineSmallCode) {
|
callee_method->instructions_size() > InlineSmallCode) {
|
||||||
return "already compiled into a big method";
|
set_msg("already compiled into a big method");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -231,17 +253,21 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
|
|||||||
const InlineTree *top = this;
|
const InlineTree *top = this;
|
||||||
while (top->caller_tree() != NULL) top = top->caller_tree();
|
while (top->caller_tree() != NULL) top = top->caller_tree();
|
||||||
ciInstanceKlass* k = top->method()->holder();
|
ciInstanceKlass* k = top->method()->holder();
|
||||||
if (!k->is_subclass_of(C->env()->Throwable_klass()))
|
if (!k->is_subclass_of(C->env()->Throwable_klass())) {
|
||||||
return "exception method";
|
set_msg("exception method");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callee_method->should_not_inline()) {
|
if (callee_method->should_not_inline()) {
|
||||||
return "disallowed by CompilerOracle";
|
set_msg("disallowed by CompilerOracle");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (ciReplay::should_not_inline(callee_method)) {
|
if (ciReplay::should_not_inline(callee_method)) {
|
||||||
return "disallowed by ciReplay";
|
set_msg("disallowed by ciReplay");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -249,19 +275,23 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
|
|||||||
// Do not inline StringCache::profile() method used only at the beginning.
|
// Do not inline StringCache::profile() method used only at the beginning.
|
||||||
if (callee_method->name() == ciSymbol::profile_name() &&
|
if (callee_method->name() == ciSymbol::profile_name() &&
|
||||||
callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
|
callee_method->holder()->name() == ciSymbol::java_lang_StringCache()) {
|
||||||
return "profiling method";
|
set_msg("profiling method");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// use frequency-based objections only for non-trivial methods
|
// use frequency-based objections only for non-trivial methods
|
||||||
if (callee_method->code_size() <= MaxTrivialSize) return NULL;
|
if (callee_method->code_size() <= MaxTrivialSize) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// don't use counts with -Xcomp or CTW
|
// don't use counts with -Xcomp or CTW
|
||||||
if (UseInterpreter && !CompileTheWorld) {
|
if (UseInterpreter && !CompileTheWorld) {
|
||||||
|
|
||||||
if (!callee_method->has_compiled_code() &&
|
if (!callee_method->has_compiled_code() &&
|
||||||
!callee_method->was_executed_more_than(0)) {
|
!callee_method->was_executed_more_than(0)) {
|
||||||
return "never executed";
|
set_msg("never executed");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_init_with_ea(callee_method, caller_method, C)) {
|
if (is_init_with_ea(callee_method, caller_method, C)) {
|
||||||
@ -270,39 +300,44 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
|
|||||||
|
|
||||||
} else if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold,
|
} else if (!callee_method->was_executed_more_than(MIN2(MinInliningThreshold,
|
||||||
CompileThreshold >> 1))) {
|
CompileThreshold >> 1))) {
|
||||||
return "executed < MinInliningThreshold times";
|
set_msg("executed < MinInliningThreshold times");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------try_to_inline-----------------------------------
|
//-----------------------------try_to_inline-----------------------------------
|
||||||
// return NULL if ok, reason for not inlining otherwise
|
// return true if ok
|
||||||
// Relocated from "InliningClosure::try_to_inline"
|
// Relocated from "InliningClosure::try_to_inline"
|
||||||
const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay) {
|
bool InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_method,
|
||||||
// Old algorithm had funny accumulating BC-size counters
|
int caller_bci, ciCallProfile& profile,
|
||||||
|
WarmCallInfo* wci_result, bool& should_delay) {
|
||||||
|
|
||||||
|
// Old algorithm had funny accumulating BC-size counters
|
||||||
if (UseOldInlining && ClipInlining
|
if (UseOldInlining && ClipInlining
|
||||||
&& (int)count_inline_bcs() >= DesiredMethodLimit) {
|
&& (int)count_inline_bcs() >= DesiredMethodLimit) {
|
||||||
if (!callee_method->force_inline() || !IncrementalInline) {
|
if (!callee_method->force_inline() || !IncrementalInline) {
|
||||||
return "size > DesiredMethodLimit";
|
set_msg("size > DesiredMethodLimit");
|
||||||
|
return false;
|
||||||
} else if (!C->inlining_incrementally()) {
|
} else if (!C->inlining_incrementally()) {
|
||||||
should_delay = true;
|
should_delay = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *msg = NULL;
|
if (!should_inline(callee_method, caller_method, caller_bci, profile,
|
||||||
msg = should_inline(callee_method, caller_method, caller_bci, profile, wci_result);
|
wci_result)) {
|
||||||
if (msg != NULL)
|
return false;
|
||||||
return msg;
|
}
|
||||||
|
if (should_not_inline(callee_method, caller_method, wci_result)) {
|
||||||
msg = should_not_inline(callee_method, caller_method, wci_result);
|
return false;
|
||||||
if (msg != NULL)
|
}
|
||||||
return msg;
|
|
||||||
|
|
||||||
if (InlineAccessors && callee_method->is_accessor()) {
|
if (InlineAccessors && callee_method->is_accessor()) {
|
||||||
// accessor methods are not subject to any of the following limits.
|
// accessor methods are not subject to any of the following limits.
|
||||||
return NULL;
|
set_msg("accessor");
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// suppress a few checks for accessors and trivial methods
|
// suppress a few checks for accessors and trivial methods
|
||||||
@ -312,7 +347,8 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
|
|||||||
if (C->over_inlining_cutoff()) {
|
if (C->over_inlining_cutoff()) {
|
||||||
if ((!callee_method->force_inline() && !caller_method->is_compiled_lambda_form())
|
if ((!callee_method->force_inline() && !caller_method->is_compiled_lambda_form())
|
||||||
|| !IncrementalInline) {
|
|| !IncrementalInline) {
|
||||||
return "NodeCountInliningCutoff";
|
set_msg("NodeCountInliningCutoff");
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
should_delay = true;
|
should_delay = true;
|
||||||
}
|
}
|
||||||
@ -326,16 +362,19 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
|
|||||||
|
|
||||||
} else if (profile.count() == 0) {
|
} else if (profile.count() == 0) {
|
||||||
// don't inline unreached call sites
|
// don't inline unreached call sites
|
||||||
return "call site not reached";
|
set_msg("call site not reached");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!C->do_inlining() && InlineAccessors) {
|
if (!C->do_inlining() && InlineAccessors) {
|
||||||
return "not an accessor";
|
set_msg("not an accessor");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
if (inline_level() > _max_inline_level) {
|
if (inline_level() > _max_inline_level) {
|
||||||
if (!callee_method->force_inline() || !IncrementalInline) {
|
if (!callee_method->force_inline() || !IncrementalInline) {
|
||||||
return "inlining too deep";
|
set_msg("inlining too deep");
|
||||||
|
return false;
|
||||||
} else if (!C->inlining_incrementally()) {
|
} else if (!C->inlining_incrementally()) {
|
||||||
should_delay = true;
|
should_delay = true;
|
||||||
}
|
}
|
||||||
@ -345,15 +384,19 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
|
|||||||
if (!callee_method->is_compiled_lambda_form()) {
|
if (!callee_method->is_compiled_lambda_form()) {
|
||||||
// count the current method and the callee
|
// count the current method and the callee
|
||||||
int inline_level = (method() == callee_method) ? 1 : 0;
|
int inline_level = (method() == callee_method) ? 1 : 0;
|
||||||
if (inline_level > MaxRecursiveInlineLevel)
|
if (inline_level > MaxRecursiveInlineLevel) {
|
||||||
return "recursively inlining too deep";
|
set_msg("recursively inlining too deep");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// count callers of current method and callee
|
// count callers of current method and callee
|
||||||
JVMState* jvms = caller_jvms();
|
JVMState* jvms = caller_jvms();
|
||||||
while (jvms != NULL && jvms->has_method()) {
|
while (jvms != NULL && jvms->has_method()) {
|
||||||
if (jvms->method() == callee_method) {
|
if (jvms->method() == callee_method) {
|
||||||
inline_level++;
|
inline_level++;
|
||||||
if (inline_level > MaxRecursiveInlineLevel)
|
if (inline_level > MaxRecursiveInlineLevel) {
|
||||||
return "recursively inlining too deep";
|
set_msg("recursively inlining too deep");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
jvms = jvms->caller();
|
jvms = jvms->caller();
|
||||||
}
|
}
|
||||||
@ -364,14 +407,15 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
|
|||||||
if (UseOldInlining && ClipInlining
|
if (UseOldInlining && ClipInlining
|
||||||
&& (int)count_inline_bcs() + size >= DesiredMethodLimit) {
|
&& (int)count_inline_bcs() + size >= DesiredMethodLimit) {
|
||||||
if (!callee_method->force_inline() || !IncrementalInline) {
|
if (!callee_method->force_inline() || !IncrementalInline) {
|
||||||
return "size > DesiredMethodLimit";
|
set_msg("size > DesiredMethodLimit");
|
||||||
|
return false;
|
||||||
} else if (!C->inlining_incrementally()) {
|
} else if (!C->inlining_incrementally()) {
|
||||||
should_delay = true;
|
should_delay = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ok, inline this method
|
// ok, inline this method
|
||||||
return NULL;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//------------------------------pass_initial_checks----------------------------
|
//------------------------------pass_initial_checks----------------------------
|
||||||
@ -421,17 +465,18 @@ const char* InlineTree::check_can_parse(ciMethod* callee) {
|
|||||||
|
|
||||||
//------------------------------print_inlining---------------------------------
|
//------------------------------print_inlining---------------------------------
|
||||||
void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci,
|
void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci,
|
||||||
const char* msg, bool success) const {
|
bool success) const {
|
||||||
assert(msg != NULL, "just checking");
|
const char* inline_msg = msg();
|
||||||
|
assert(inline_msg != NULL, "just checking");
|
||||||
if (C->log() != NULL) {
|
if (C->log() != NULL) {
|
||||||
if (success) {
|
if (success) {
|
||||||
C->log()->inline_success(msg);
|
C->log()->inline_success(inline_msg);
|
||||||
} else {
|
} else {
|
||||||
C->log()->inline_fail(msg);
|
C->log()->inline_fail(inline_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (PrintInlining) {
|
if (PrintInlining) {
|
||||||
C->print_inlining(callee_method, inline_level(), caller_bci, msg);
|
C->print_inlining(callee_method, inline_level(), caller_bci, inline_msg);
|
||||||
if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
|
if (callee_method == NULL) tty->print(" callee not monotonic or profiled");
|
||||||
if (Verbose && callee_method) {
|
if (Verbose && callee_method) {
|
||||||
const InlineTree *top = this;
|
const InlineTree *top = this;
|
||||||
@ -455,49 +500,51 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
|
|||||||
}
|
}
|
||||||
assert(_method == jvms->method(), "redundant instance state");
|
assert(_method == jvms->method(), "redundant instance state");
|
||||||
#endif
|
#endif
|
||||||
const char *failure_msg = NULL;
|
|
||||||
int caller_bci = jvms->bci();
|
int caller_bci = jvms->bci();
|
||||||
ciMethod *caller_method = jvms->method();
|
ciMethod* caller_method = jvms->method();
|
||||||
|
|
||||||
// Do some initial checks.
|
// Do some initial checks.
|
||||||
if (!pass_initial_checks(caller_method, caller_bci, callee_method)) {
|
if (!pass_initial_checks(caller_method, caller_bci, callee_method)) {
|
||||||
print_inlining(callee_method, caller_bci, "failed initial checks",
|
set_msg("failed initial checks");
|
||||||
false /* !success */);
|
print_inlining(callee_method, caller_bci, false /* !success */);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do some parse checks.
|
// Do some parse checks.
|
||||||
failure_msg = check_can_parse(callee_method);
|
set_msg(check_can_parse(callee_method));
|
||||||
if (failure_msg != NULL) {
|
if (msg() != NULL) {
|
||||||
print_inlining(callee_method, caller_bci, failure_msg,
|
print_inlining(callee_method, caller_bci, false /* !success */);
|
||||||
false /* !success */);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if inlining policy says no.
|
// Check if inlining policy says no.
|
||||||
WarmCallInfo wci = *(initial_wci);
|
WarmCallInfo wci = *(initial_wci);
|
||||||
failure_msg = try_to_inline(callee_method, caller_method, caller_bci, profile,
|
bool success = try_to_inline(callee_method, caller_method, caller_bci,
|
||||||
&wci, should_delay);
|
profile, &wci, should_delay);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
if (UseOldInlining && InlineWarmCalls
|
if (UseOldInlining && InlineWarmCalls
|
||||||
&& (PrintOpto || PrintOptoInlining || PrintInlining)) {
|
&& (PrintOpto || PrintOptoInlining || PrintInlining)) {
|
||||||
bool cold = wci.is_cold();
|
bool cold = wci.is_cold();
|
||||||
bool hot = !cold && wci.is_hot();
|
bool hot = !cold && wci.is_hot();
|
||||||
bool old_cold = (failure_msg != NULL);
|
bool old_cold = !success;
|
||||||
if (old_cold != cold || (Verbose || WizardMode)) {
|
if (old_cold != cold || (Verbose || WizardMode)) {
|
||||||
|
if (msg() == NULL) {
|
||||||
|
set_msg("OK");
|
||||||
|
}
|
||||||
tty->print(" OldInlining= %4s : %s\n WCI=",
|
tty->print(" OldInlining= %4s : %s\n WCI=",
|
||||||
old_cold ? "cold" : "hot", failure_msg ? failure_msg : "OK");
|
old_cold ? "cold" : "hot", msg());
|
||||||
wci.print();
|
wci.print();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (UseOldInlining) {
|
if (UseOldInlining) {
|
||||||
if (failure_msg == NULL)
|
if (success) {
|
||||||
wci = *(WarmCallInfo::always_hot());
|
wci = *(WarmCallInfo::always_hot());
|
||||||
else
|
} else {
|
||||||
wci = *(WarmCallInfo::always_cold());
|
wci = *(WarmCallInfo::always_cold());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (!InlineWarmCalls) {
|
if (!InlineWarmCalls) {
|
||||||
if (!wci.is_cold() && !wci.is_hot()) {
|
if (!wci.is_cold() && !wci.is_hot()) {
|
||||||
// Do not inline the warm calls.
|
// Do not inline the warm calls.
|
||||||
@ -507,9 +554,10 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
|
|||||||
|
|
||||||
if (!wci.is_cold()) {
|
if (!wci.is_cold()) {
|
||||||
// Inline!
|
// Inline!
|
||||||
print_inlining(callee_method, caller_bci,
|
if (msg() == NULL) {
|
||||||
failure_msg ? failure_msg : "inline (hot)",
|
set_msg("inline (hot)");
|
||||||
true /* success */);
|
}
|
||||||
|
print_inlining(callee_method, caller_bci, true /* success */);
|
||||||
if (UseOldInlining)
|
if (UseOldInlining)
|
||||||
build_inline_tree_for_callee(callee_method, jvms, caller_bci);
|
build_inline_tree_for_callee(callee_method, jvms, caller_bci);
|
||||||
if (InlineWarmCalls && !wci.is_hot())
|
if (InlineWarmCalls && !wci.is_hot())
|
||||||
@ -518,9 +566,10 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do not inline
|
// Do not inline
|
||||||
print_inlining(callee_method, caller_bci,
|
if (msg() == NULL) {
|
||||||
failure_msg ? failure_msg : "too cold to inline",
|
set_msg("too cold to inline");
|
||||||
false /* !success */ );
|
}
|
||||||
|
print_inlining(callee_method, caller_bci, false /* !success */ );
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,6 +320,9 @@ Node *MemNode::Ideal_common(PhaseGVN *phase, bool can_reshape) {
|
|||||||
|
|
||||||
if (mem != old_mem) {
|
if (mem != old_mem) {
|
||||||
set_req(MemNode::Memory, mem);
|
set_req(MemNode::Memory, mem);
|
||||||
|
if (can_reshape && old_mem->outcnt() == 0) {
|
||||||
|
igvn->_worklist.push(old_mem);
|
||||||
|
}
|
||||||
if (phase->type( mem ) == Type::TOP) return NodeSentinel;
|
if (phase->type( mem ) == Type::TOP) return NodeSentinel;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -2319,9 +2322,9 @@ Node *StoreNode::Ideal(PhaseGVN *phase, bool can_reshape) {
|
|||||||
if (ReduceFieldZeroing && /*can_reshape &&*/
|
if (ReduceFieldZeroing && /*can_reshape &&*/
|
||||||
mem->is_Proj() && mem->in(0)->is_Initialize()) {
|
mem->is_Proj() && mem->in(0)->is_Initialize()) {
|
||||||
InitializeNode* init = mem->in(0)->as_Initialize();
|
InitializeNode* init = mem->in(0)->as_Initialize();
|
||||||
intptr_t offset = init->can_capture_store(this, phase);
|
intptr_t offset = init->can_capture_store(this, phase, can_reshape);
|
||||||
if (offset > 0) {
|
if (offset > 0) {
|
||||||
Node* moved = init->capture_store(this, offset, phase);
|
Node* moved = init->capture_store(this, offset, phase, can_reshape);
|
||||||
// If the InitializeNode captured me, it made a raw copy of me,
|
// If the InitializeNode captured me, it made a raw copy of me,
|
||||||
// and I need to disappear.
|
// and I need to disappear.
|
||||||
if (moved != NULL) {
|
if (moved != NULL) {
|
||||||
@ -3134,7 +3137,7 @@ bool InitializeNode::detect_init_independence(Node* n,
|
|||||||
// an initialization. Returns zero if a check fails.
|
// an initialization. Returns zero if a check fails.
|
||||||
// On success, returns the (constant) offset to which the store applies,
|
// On success, returns the (constant) offset to which the store applies,
|
||||||
// within the initialized memory.
|
// within the initialized memory.
|
||||||
intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase) {
|
intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape) {
|
||||||
const int FAIL = 0;
|
const int FAIL = 0;
|
||||||
if (st->req() != MemNode::ValueIn + 1)
|
if (st->req() != MemNode::ValueIn + 1)
|
||||||
return FAIL; // an inscrutable StoreNode (card mark?)
|
return FAIL; // an inscrutable StoreNode (card mark?)
|
||||||
@ -3156,6 +3159,91 @@ intptr_t InitializeNode::can_capture_store(StoreNode* st, PhaseTransform* phase)
|
|||||||
if (!detect_init_independence(val, true, complexity_count))
|
if (!detect_init_independence(val, true, complexity_count))
|
||||||
return FAIL; // stored value must be 'simple enough'
|
return FAIL; // stored value must be 'simple enough'
|
||||||
|
|
||||||
|
// The Store can be captured only if nothing after the allocation
|
||||||
|
// and before the Store is using the memory location that the store
|
||||||
|
// overwrites.
|
||||||
|
bool failed = false;
|
||||||
|
// If is_complete_with_arraycopy() is true the shape of the graph is
|
||||||
|
// well defined and is safe so no need for extra checks.
|
||||||
|
if (!is_complete_with_arraycopy()) {
|
||||||
|
// We are going to look at each use of the memory state following
|
||||||
|
// the allocation to make sure nothing reads the memory that the
|
||||||
|
// Store writes.
|
||||||
|
const TypePtr* t_adr = phase->type(adr)->isa_ptr();
|
||||||
|
int alias_idx = phase->C->get_alias_index(t_adr);
|
||||||
|
ResourceMark rm;
|
||||||
|
Unique_Node_List mems;
|
||||||
|
mems.push(mem);
|
||||||
|
Node* unique_merge = NULL;
|
||||||
|
for (uint next = 0; next < mems.size(); ++next) {
|
||||||
|
Node *m = mems.at(next);
|
||||||
|
for (DUIterator_Fast jmax, j = m->fast_outs(jmax); j < jmax; j++) {
|
||||||
|
Node *n = m->fast_out(j);
|
||||||
|
if (n->outcnt() == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (n == st) {
|
||||||
|
continue;
|
||||||
|
} else if (n->in(0) != NULL && n->in(0) != ctl) {
|
||||||
|
// If the control of this use is different from the control
|
||||||
|
// of the Store which is right after the InitializeNode then
|
||||||
|
// this node cannot be between the InitializeNode and the
|
||||||
|
// Store.
|
||||||
|
continue;
|
||||||
|
} else if (n->is_MergeMem()) {
|
||||||
|
if (n->as_MergeMem()->memory_at(alias_idx) == m) {
|
||||||
|
// We can hit a MergeMemNode (that will likely go away
|
||||||
|
// later) that is a direct use of the memory state
|
||||||
|
// following the InitializeNode on the same slice as the
|
||||||
|
// store node that we'd like to capture. We need to check
|
||||||
|
// the uses of the MergeMemNode.
|
||||||
|
mems.push(n);
|
||||||
|
}
|
||||||
|
} else if (n->is_Mem()) {
|
||||||
|
Node* other_adr = n->in(MemNode::Address);
|
||||||
|
if (other_adr == adr) {
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
const TypePtr* other_t_adr = phase->type(other_adr)->isa_ptr();
|
||||||
|
if (other_t_adr != NULL) {
|
||||||
|
int other_alias_idx = phase->C->get_alias_index(other_t_adr);
|
||||||
|
if (other_alias_idx == alias_idx) {
|
||||||
|
// A load from the same memory slice as the store right
|
||||||
|
// after the InitializeNode. We check the control of the
|
||||||
|
// object/array that is loaded from. If it's the same as
|
||||||
|
// the store control then we cannot capture the store.
|
||||||
|
assert(!n->is_Store(), "2 stores to same slice on same control?");
|
||||||
|
Node* base = other_adr;
|
||||||
|
assert(base->is_AddP(), err_msg_res("should be addp but is %s", base->Name()));
|
||||||
|
base = base->in(AddPNode::Base);
|
||||||
|
if (base != NULL) {
|
||||||
|
base = base->uncast();
|
||||||
|
if (base->is_Proj() && base->in(0) == alloc) {
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
failed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (failed) {
|
||||||
|
if (!can_reshape) {
|
||||||
|
// We decided we couldn't capture the store during parsing. We
|
||||||
|
// should try again during the next IGVN once the graph is
|
||||||
|
// cleaner.
|
||||||
|
phase->C->record_for_igvn(st);
|
||||||
|
}
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
return offset; // success
|
return offset; // success
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3266,11 +3354,11 @@ Node* InitializeNode::make_raw_address(intptr_t offset,
|
|||||||
// rawstore1 rawstore2)
|
// rawstore1 rawstore2)
|
||||||
//
|
//
|
||||||
Node* InitializeNode::capture_store(StoreNode* st, intptr_t start,
|
Node* InitializeNode::capture_store(StoreNode* st, intptr_t start,
|
||||||
PhaseTransform* phase) {
|
PhaseTransform* phase, bool can_reshape) {
|
||||||
assert(stores_are_sane(phase), "");
|
assert(stores_are_sane(phase), "");
|
||||||
|
|
||||||
if (start < 0) return NULL;
|
if (start < 0) return NULL;
|
||||||
assert(can_capture_store(st, phase) == start, "sanity");
|
assert(can_capture_store(st, phase, can_reshape) == start, "sanity");
|
||||||
|
|
||||||
Compile* C = phase->C;
|
Compile* C = phase->C;
|
||||||
int size_in_bytes = st->memory_size();
|
int size_in_bytes = st->memory_size();
|
||||||
|
@ -1072,11 +1072,11 @@ public:
|
|||||||
|
|
||||||
// See if this store can be captured; return offset where it initializes.
|
// See if this store can be captured; return offset where it initializes.
|
||||||
// Return 0 if the store cannot be moved (any sort of problem).
|
// Return 0 if the store cannot be moved (any sort of problem).
|
||||||
intptr_t can_capture_store(StoreNode* st, PhaseTransform* phase);
|
intptr_t can_capture_store(StoreNode* st, PhaseTransform* phase, bool can_reshape);
|
||||||
|
|
||||||
// Capture another store; reformat it to write my internal raw memory.
|
// Capture another store; reformat it to write my internal raw memory.
|
||||||
// Return the captured copy, else NULL if there is some sort of problem.
|
// Return the captured copy, else NULL if there is some sort of problem.
|
||||||
Node* capture_store(StoreNode* st, intptr_t start, PhaseTransform* phase);
|
Node* capture_store(StoreNode* st, intptr_t start, PhaseTransform* phase, bool can_reshape);
|
||||||
|
|
||||||
// Find captured store which corresponds to the range [start..start+size).
|
// Find captured store which corresponds to the range [start..start+size).
|
||||||
// Return my own memory projection (meaning the initial zero bits)
|
// Return my own memory projection (meaning the initial zero bits)
|
||||||
|
@ -1261,6 +1261,7 @@ static void kill_dead_code( Node *dead, PhaseIterGVN *igvn ) {
|
|||||||
if (dead->is_expensive()) {
|
if (dead->is_expensive()) {
|
||||||
igvn->C->remove_expensive_node(dead);
|
igvn->C->remove_expensive_node(dead);
|
||||||
}
|
}
|
||||||
|
igvn->C->record_dead_node(dead->_idx);
|
||||||
// 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
|
||||||
|
@ -58,7 +58,7 @@ class InlineTree : public ResourceObj {
|
|||||||
GrowableArray<InlineTree*> _subtrees;
|
GrowableArray<InlineTree*> _subtrees;
|
||||||
|
|
||||||
void print_impl(outputStream* stj, int indent) const PRODUCT_RETURN;
|
void print_impl(outputStream* stj, int indent) const PRODUCT_RETURN;
|
||||||
|
const char* _msg;
|
||||||
protected:
|
protected:
|
||||||
InlineTree(Compile* C,
|
InlineTree(Compile* C,
|
||||||
const InlineTree* caller_tree,
|
const InlineTree* caller_tree,
|
||||||
@ -70,17 +70,29 @@ protected:
|
|||||||
InlineTree *build_inline_tree_for_callee(ciMethod* callee_method,
|
InlineTree *build_inline_tree_for_callee(ciMethod* callee_method,
|
||||||
JVMState* caller_jvms,
|
JVMState* caller_jvms,
|
||||||
int caller_bci);
|
int caller_bci);
|
||||||
const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result, bool& should_delay);
|
bool try_to_inline(ciMethod* callee_method,
|
||||||
const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const;
|
ciMethod* caller_method,
|
||||||
const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const;
|
int caller_bci,
|
||||||
|
ciCallProfile& profile,
|
||||||
|
WarmCallInfo* wci_result,
|
||||||
|
bool& should_delay);
|
||||||
|
bool should_inline(ciMethod* callee_method,
|
||||||
|
ciMethod* caller_method,
|
||||||
|
int caller_bci,
|
||||||
|
ciCallProfile& profile,
|
||||||
|
WarmCallInfo* wci_result);
|
||||||
|
bool should_not_inline(ciMethod* callee_method,
|
||||||
|
ciMethod* caller_method,
|
||||||
|
WarmCallInfo* wci_result);
|
||||||
void print_inlining(ciMethod* callee_method, int caller_bci,
|
void print_inlining(ciMethod* callee_method, int caller_bci,
|
||||||
const char* msg, bool success) const;
|
bool success) const;
|
||||||
|
|
||||||
InlineTree *caller_tree() const { return _caller_tree; }
|
InlineTree* caller_tree() const { return _caller_tree; }
|
||||||
InlineTree* callee_at(int bci, ciMethod* m) const;
|
InlineTree* callee_at(int bci, ciMethod* m) const;
|
||||||
int inline_level() const { return stack_depth(); }
|
int inline_level() const { return stack_depth(); }
|
||||||
int stack_depth() const { return _caller_jvms ? _caller_jvms->depth() : 0; }
|
int stack_depth() const { return _caller_jvms ? _caller_jvms->depth() : 0; }
|
||||||
|
const char* msg() const { return _msg; }
|
||||||
|
void set_msg(const char* msg) { _msg = msg; }
|
||||||
public:
|
public:
|
||||||
static const char* check_can_parse(ciMethod* callee);
|
static const char* check_can_parse(ciMethod* callee);
|
||||||
|
|
||||||
|
@ -1197,6 +1197,18 @@ void PhaseIterGVN::remove_globally_dead_node( Node *dead ) {
|
|||||||
assert(!(i < imax), "sanity");
|
assert(!(i < imax), "sanity");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ReduceFieldZeroing && dead->is_Load() && i == MemNode::Memory &&
|
||||||
|
in->is_Proj() && in->in(0) != NULL && in->in(0)->is_Initialize()) {
|
||||||
|
// A Load that directly follows an InitializeNode is
|
||||||
|
// going away. The Stores that follow are candidates
|
||||||
|
// again to be captured by the InitializeNode.
|
||||||
|
for (DUIterator_Fast jmax, j = in->fast_outs(jmax); j < jmax; j++) {
|
||||||
|
Node *n = in->fast_out(j);
|
||||||
|
if (n->is_Store()) {
|
||||||
|
_worklist.push(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
C->record_dead_node(dead->_idx);
|
C->record_dead_node(dead->_idx);
|
||||||
|
@ -2181,19 +2181,6 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) {
|
|||||||
FREE_C_HEAP_ARRAY(char, altclasses_path, mtInternal);
|
FREE_C_HEAP_ARRAY(char, altclasses_path, mtInternal);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WhiteBoxAPI) {
|
|
||||||
// Append wb.jar to bootclasspath if enabled
|
|
||||||
const char* wb_jar = "wb.jar";
|
|
||||||
size_t wb_path_len = strlen(get_meta_index_dir()) + 1 +
|
|
||||||
strlen(wb_jar);
|
|
||||||
char* wb_path = NEW_C_HEAP_ARRAY(char, wb_path_len, mtInternal);
|
|
||||||
strcpy(wb_path, get_meta_index_dir());
|
|
||||||
strcat(wb_path, wb_jar);
|
|
||||||
scp.add_suffix(wb_path);
|
|
||||||
scp_assembly_required = true;
|
|
||||||
FREE_C_HEAP_ARRAY(char, wb_path, mtInternal);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM)
|
// Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM)
|
||||||
result = parse_java_options_environment_variable(&scp, &scp_assembly_required);
|
result = parse_java_options_environment_variable(&scp, &scp_assembly_required);
|
||||||
if (result != JNI_OK) {
|
if (result != JNI_OK) {
|
||||||
|
@ -29,10 +29,17 @@
|
|||||||
|
|
||||||
class Atomic : AllStatic {
|
class Atomic : AllStatic {
|
||||||
public:
|
public:
|
||||||
|
// Atomic operations on jlong types are not available on all 32-bit
|
||||||
|
// platforms. If atomic ops on jlongs are defined here they must only
|
||||||
|
// be used from code that verifies they are available at runtime and
|
||||||
|
// can provide an alternative action if not - see supports_cx8() for
|
||||||
|
// a means to test availability.
|
||||||
|
|
||||||
// Atomically store to a location
|
// Atomically store to a location
|
||||||
inline static void store (jbyte store_value, jbyte* dest);
|
inline static void store (jbyte store_value, jbyte* dest);
|
||||||
inline static void store (jshort store_value, jshort* dest);
|
inline static void store (jshort store_value, jshort* dest);
|
||||||
inline static void store (jint store_value, jint* dest);
|
inline static void store (jint store_value, jint* dest);
|
||||||
|
// See comment above about using jlong atomics on 32-bit platforms
|
||||||
inline static void store (jlong store_value, jlong* dest);
|
inline static void store (jlong store_value, jlong* dest);
|
||||||
inline static void store_ptr(intptr_t store_value, intptr_t* dest);
|
inline static void store_ptr(intptr_t store_value, intptr_t* dest);
|
||||||
inline static void store_ptr(void* store_value, void* dest);
|
inline static void store_ptr(void* store_value, void* dest);
|
||||||
@ -40,17 +47,19 @@ class Atomic : AllStatic {
|
|||||||
inline static void store (jbyte store_value, volatile jbyte* dest);
|
inline static void store (jbyte store_value, volatile jbyte* dest);
|
||||||
inline static void store (jshort store_value, volatile jshort* dest);
|
inline static void store (jshort store_value, volatile jshort* dest);
|
||||||
inline static void store (jint store_value, volatile jint* dest);
|
inline static void store (jint store_value, volatile jint* dest);
|
||||||
|
// See comment above about using jlong atomics on 32-bit platforms
|
||||||
inline static void store (jlong store_value, volatile jlong* dest);
|
inline static void store (jlong store_value, volatile jlong* dest);
|
||||||
inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest);
|
inline static void store_ptr(intptr_t store_value, volatile intptr_t* dest);
|
||||||
inline static void store_ptr(void* store_value, volatile void* dest);
|
inline static void store_ptr(void* store_value, volatile void* dest);
|
||||||
|
|
||||||
|
// See comment above about using jlong atomics on 32-bit platforms
|
||||||
inline static jlong load(volatile jlong* src);
|
inline static jlong load(volatile jlong* src);
|
||||||
|
|
||||||
// Atomically add to a location, return updated value
|
// Atomically add to a location, return updated value
|
||||||
inline static jint add (jint add_value, volatile jint* dest);
|
inline static jint add (jint add_value, volatile jint* dest);
|
||||||
inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
|
inline static intptr_t add_ptr(intptr_t add_value, volatile intptr_t* dest);
|
||||||
inline static void* add_ptr(intptr_t add_value, volatile void* dest);
|
inline static void* add_ptr(intptr_t add_value, volatile void* dest);
|
||||||
|
// See comment above about using jlong atomics on 32-bit platforms
|
||||||
static jlong add (jlong add_value, volatile jlong* dest);
|
static jlong add (jlong add_value, volatile jlong* dest);
|
||||||
|
|
||||||
// Atomically increment location
|
// Atomically increment location
|
||||||
@ -75,6 +84,7 @@ class Atomic : AllStatic {
|
|||||||
// barrier across the cmpxchg. I.e., it's really a 'fence_cmpxchg_acquire'.
|
// barrier across the cmpxchg. I.e., it's really a 'fence_cmpxchg_acquire'.
|
||||||
static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value);
|
static jbyte cmpxchg (jbyte exchange_value, volatile jbyte* dest, jbyte compare_value);
|
||||||
inline static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value);
|
inline static jint cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value);
|
||||||
|
// See comment above about using jlong atomics on 32-bit platforms
|
||||||
inline static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value);
|
inline static jlong cmpxchg (jlong exchange_value, volatile jlong* dest, jlong compare_value);
|
||||||
|
|
||||||
static unsigned int cmpxchg(unsigned int exchange_value,
|
static unsigned int cmpxchg(unsigned int exchange_value,
|
||||||
|
@ -528,7 +528,8 @@ bool MemSnapshot::promote_malloc_records(MemPointerArrayIterator* itr) {
|
|||||||
// an arena record can be followed by a size record, we need to remove both
|
// an arena record can be followed by a size record, we need to remove both
|
||||||
if (matched_rec->is_arena_record()) {
|
if (matched_rec->is_arena_record()) {
|
||||||
MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next();
|
MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next();
|
||||||
if (next->is_arena_memory_record() && next->is_memory_record_of_arena(matched_rec)) {
|
if (next != NULL && next->is_arena_memory_record() &&
|
||||||
|
next->is_memory_record_of_arena(matched_rec)) {
|
||||||
malloc_snapshot_itr.remove();
|
malloc_snapshot_itr.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
@ -52,7 +52,6 @@ BasicType constantTag::basic_type() const {
|
|||||||
case JVM_CONSTANT_StringIndex :
|
case JVM_CONSTANT_StringIndex :
|
||||||
case JVM_CONSTANT_MethodHandle :
|
case JVM_CONSTANT_MethodHandle :
|
||||||
case JVM_CONSTANT_MethodType :
|
case JVM_CONSTANT_MethodType :
|
||||||
case JVM_CONSTANT_Object :
|
|
||||||
return T_OBJECT;
|
return T_OBJECT;
|
||||||
default:
|
default:
|
||||||
ShouldNotReachHere();
|
ShouldNotReachHere();
|
||||||
@ -96,8 +95,6 @@ const char* constantTag::internal_name() const {
|
|||||||
return "MethodType Error";
|
return "MethodType Error";
|
||||||
case JVM_CONSTANT_InvokeDynamic :
|
case JVM_CONSTANT_InvokeDynamic :
|
||||||
return "InvokeDynamic";
|
return "InvokeDynamic";
|
||||||
case JVM_CONSTANT_Object :
|
|
||||||
return "Object";
|
|
||||||
case JVM_CONSTANT_Utf8 :
|
case JVM_CONSTANT_Utf8 :
|
||||||
return "Utf8";
|
return "Utf8";
|
||||||
case JVM_CONSTANT_UnresolvedClass :
|
case JVM_CONSTANT_UnresolvedClass :
|
||||||
|
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