aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoramurillo <none@none>2012-03-02 16:27:09 -0800
committeramurillo <none@none>2012-03-02 16:27:09 -0800
commit97c42b34d2dfafd130c48c476b549baecd100119 (patch)
treef22e00b2b2adef195b025b9614466c668c337e95
parent38dff4eb1da65c8a14b7a8c08fe127db3fe8d053 (diff)
parentb1be6fb7ff7314588befbe79ee95cd3993b4084a (diff)
-rw-r--r--make/bsd/makefiles/buildtree.make3
-rw-r--r--make/bsd/makefiles/gcc.make86
-rw-r--r--make/bsd/makefiles/sparcWorks.make15
-rw-r--r--make/defs.make5
-rw-r--r--make/hotspot_version2
-rw-r--r--make/linux/makefiles/buildtree.make3
-rw-r--r--make/linux/makefiles/gcc.make37
-rw-r--r--make/linux/makefiles/sparcWorks.make15
-rw-r--r--make/solaris/makefiles/buildtree.make3
-rw-r--r--make/solaris/makefiles/gcc.make12
-rw-r--r--make/solaris/makefiles/sparcWorks.make25
-rw-r--r--make/windows/build.make4
-rw-r--r--make/windows/makefiles/compile.make12
-rw-r--r--make/windows/makefiles/defs.make16
-rw-r--r--src/cpu/x86/vm/c1_Runtime1_x86.cpp22
-rw-r--r--src/cpu/x86/vm/sharedRuntime_x86_64.cpp260
-rw-r--r--src/cpu/x86/vm/stubGenerator_x86_64.cpp16
-rw-r--r--src/cpu/x86/vm/stubRoutines_x86_64.cpp1
-rw-r--r--src/cpu/x86/vm/stubRoutines_x86_64.hpp6
-rw-r--r--src/os/linux/vm/os_linux.cpp4
-rw-r--r--src/os/solaris/vm/os_solaris.cpp9
-rw-r--r--src/os/windows/vm/os_windows.cpp10
-rw-r--r--src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp5
-rw-r--r--src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp5
-rw-r--r--src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp5
-rw-r--r--src/os_cpu/linux_x86/vm/os_linux_x86.cpp8
-rw-r--r--src/os_cpu/linux_zero/vm/os_linux_zero.cpp5
-rw-r--r--src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp14
-rw-r--r--src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp14
-rw-r--r--src/os_cpu/solaris_x86/vm/solaris_x86_32.il6
-rw-r--r--src/os_cpu/solaris_x86/vm/solaris_x86_64.il6
-rw-r--r--src/os_cpu/windows_x86/vm/os_windows_x86.cpp28
-rw-r--r--src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java26
-rw-r--r--src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java57
-rw-r--r--src/share/vm/c1/c1_LinearScan.cpp2
-rw-r--r--src/share/vm/classfile/vmSymbols.hpp5
-rw-r--r--src/share/vm/oops/cpCacheOop.cpp18
-rw-r--r--src/share/vm/opto/connode.cpp4
-rw-r--r--src/share/vm/opto/escape.cpp38
-rw-r--r--src/share/vm/runtime/interfaceSupport.hpp3
-rw-r--r--src/share/vm/runtime/os.hpp2
-rw-r--r--src/share/vm/services/diagnosticCommand.cpp189
-rw-r--r--src/share/vm/services/diagnosticCommand.hpp80
43 files changed, 877 insertions, 209 deletions
diff --git a/make/bsd/makefiles/buildtree.make b/make/bsd/makefiles/buildtree.make
index 960a382bb..ccc812775 100644
--- a/make/bsd/makefiles/buildtree.make
+++ b/make/bsd/makefiles/buildtree.make
@@ -58,6 +58,7 @@
# needs to be set here since this Makefile doesn't include defs.make
OS_VENDOR:=$(shell uname -s)
+-include $(SPEC)
include $(GAMMADIR)/make/scm.make
include $(GAMMADIR)/make/altsrc.make
@@ -247,6 +248,8 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \
echo; \
+ [ -n "$(SPEC)" ] && \
+ echo "include $(SPEC)"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
) > $@
diff --git a/make/bsd/makefiles/gcc.make b/make/bsd/makefiles/gcc.make
index d7a6422eb..a73397bf0 100644
--- a/make/bsd/makefiles/gcc.make
+++ b/make/bsd/makefiles/gcc.make
@@ -27,53 +27,57 @@ OS_VENDOR = $(shell uname -s)
#------------------------------------------------------------------------
# CC, CXX & AS
-# When cross-compiling the ALT_COMPILER_PATH points
-# to the cross-compilation toolset
-ifdef CROSS_COMPILE_ARCH
- CXX = $(ALT_COMPILER_PATH)/g++
- CC = $(ALT_COMPILER_PATH)/gcc
- HOSTCXX = g++
- HOSTCC = gcc
-else ifneq ($(OS_VENDOR), Darwin)
- CXX = g++
- CC = gcc
- HOSTCXX = $(CXX)
- HOSTCC = $(CC)
-endif
-
-# i486 hotspot requires -mstackrealign on Darwin.
-# llvm-gcc supports this in Xcode 3.2.6 and 4.0.
-# gcc-4.0 supports this on earlier versions.
-# Prefer llvm-gcc where available.
-ifeq ($(OS_VENDOR), Darwin)
- ifeq ($(origin CXX), default)
- CXX = llvm-g++
- endif
- ifeq ($(origin CC), default)
- CC = llvm-gcc
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+ # When cross-compiling the ALT_COMPILER_PATH points
+ # to the cross-compilation toolset
+ ifdef CROSS_COMPILE_ARCH
+ CXX = $(ALT_COMPILER_PATH)/g++
+ CC = $(ALT_COMPILER_PATH)/gcc
+ HOSTCXX = g++
+ HOSTCC = gcc
+ else ifneq ($(OS_VENDOR), Darwin)
+ CXX = g++
+ CC = gcc
+ HOSTCXX = $(CXX)
+ HOSTCC = $(CC)
endif
- ifeq ($(ARCH), i486)
- LLVM_SUPPORTS_STACKREALIGN := $(shell \
- [ "0"`llvm-gcc -v 2>&1 | grep LLVM | sed -E "s/.*LLVM build ([0-9]+).*/\1/"` -gt "2333" ] \
- && echo true || echo false)
-
- ifeq ($(LLVM_SUPPORTS_STACKREALIGN), true)
- CXX32 ?= llvm-g++
- CC32 ?= llvm-gcc
- else
- CXX32 ?= g++-4.0
- CC32 ?= gcc-4.0
- endif
- CXX = $(CXX32)
- CC = $(CC32)
+ # i486 hotspot requires -mstackrealign on Darwin.
+ # llvm-gcc supports this in Xcode 3.2.6 and 4.0.
+ # gcc-4.0 supports this on earlier versions.
+ # Prefer llvm-gcc where available.
+ ifeq ($(OS_VENDOR), Darwin)
+ ifeq ($(origin CXX), default)
+ CXX = llvm-g++
+ endif
+ ifeq ($(origin CC), default)
+ CC = llvm-gcc
+ endif
+
+ ifeq ($(ARCH), i486)
+ LLVM_SUPPORTS_STACKREALIGN := $(shell \
+ [ "0"`llvm-gcc -v 2>&1 | grep LLVM | sed -E "s/.*LLVM build ([0-9]+).*/\1/"` -gt "2333" ] \
+ && echo true || echo false)
+
+ ifeq ($(LLVM_SUPPORTS_STACKREALIGN), true)
+ CXX32 ?= llvm-g++
+ CC32 ?= llvm-gcc
+ else
+ CXX32 ?= g++-4.0
+ CC32 ?= gcc-4.0
+ endif
+ CXX = $(CXX32)
+ CC = $(CC32)
+ endif
+
+ HOSTCXX = $(CXX)
+ HOSTCC = $(CC)
endif
- HOSTCXX = $(CXX)
- HOSTCC = $(CC)
+ AS = $(CC) -c -x assembler-with-cpp
endif
-AS = $(CC) -c -x assembler-with-cpp
# -dumpversion in gcc-2.91 shows "egcs-2.91.66". In later version, it only
# prints the numbers (e.g. "2.95", "3.2.1")
diff --git a/make/bsd/makefiles/sparcWorks.make b/make/bsd/makefiles/sparcWorks.make
index 81de9c33b..c87f50440 100644
--- a/make/bsd/makefiles/sparcWorks.make
+++ b/make/bsd/makefiles/sparcWorks.make
@@ -25,12 +25,15 @@
#------------------------------------------------------------------------
# CC, CXX & AS
-CXX = CC
-CC = cc
-AS = $(CC) -c
-
-HOSTCXX = $(CXX)
-HOSTCC = $(CC)
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+ CXX = CC
+ CC = cc
+ AS = $(CC) -c
+
+ HOSTCXX = $(CXX)
+ HOSTCC = $(CC)
+endif
ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
ARCHFLAG/i486 = -m32
diff --git a/make/defs.make b/make/defs.make
index a0aa0e5c8..ac7268a96 100644
--- a/make/defs.make
+++ b/make/defs.make
@@ -24,6 +24,11 @@
# The common definitions for hotspot builds.
+# Optionally include SPEC file generated by configure.
+ifneq ($(SPEC),)
+ include $(SPEC)
+endif
+
# Default to verbose build logs (show all compile lines):
MAKE_VERBOSE=y
diff --git a/make/hotspot_version b/make/hotspot_version
index f67badd6d..6cc9716c9 100644
--- a/make/hotspot_version
+++ b/make/hotspot_version
@@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2011
HS_MAJOR_VER=24
HS_MINOR_VER=0
-HS_BUILD_NUMBER=01
+HS_BUILD_NUMBER=02
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
diff --git a/make/linux/makefiles/buildtree.make b/make/linux/makefiles/buildtree.make
index 5bc29368e..6af5490da 100644
--- a/make/linux/makefiles/buildtree.make
+++ b/make/linux/makefiles/buildtree.make
@@ -55,6 +55,7 @@
# The makefiles are split this way so that "make foo" will run faster by not
# having to read the dependency files for the vm.
+-include $(SPEC)
include $(GAMMADIR)/make/scm.make
include $(GAMMADIR)/make/altsrc.make
@@ -244,6 +245,8 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \
echo; \
+ [ -n "$(SPEC)" ] && \
+ echo "include $(SPEC)"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
) > $@
diff --git a/make/linux/makefiles/gcc.make b/make/linux/makefiles/gcc.make
index 0188ed772..d918ef77b 100644
--- a/make/linux/makefiles/gcc.make
+++ b/make/linux/makefiles/gcc.make
@@ -25,21 +25,26 @@
#------------------------------------------------------------------------
# CC, CXX & AS
-# When cross-compiling the ALT_COMPILER_PATH points
-# to the cross-compilation toolset
-ifdef CROSS_COMPILE_ARCH
-CXX = $(ALT_COMPILER_PATH)/g++
-CC = $(ALT_COMPILER_PATH)/gcc
-HOSTCXX = g++
-HOSTCC = gcc
-else
-CXX = g++
-CC = gcc
-HOSTCXX = $(CXX)
-HOSTCC = $(CC)
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+ # When cross-compiling the ALT_COMPILER_PATH points
+ # to the cross-compilation toolset
+ ifdef CROSS_COMPILE_ARCH
+ CXX = $(ALT_COMPILER_PATH)/g++
+ CC = $(ALT_COMPILER_PATH)/gcc
+ HOSTCXX = g++
+ HOSTCC = gcc
+ STRIP = $(ALT_COMPILER_PATH)/strip
+ else
+ CXX = g++
+ CC = gcc
+ HOSTCXX = $(CXX)
+ HOSTCC = $(CC)
+ STRIP = strip
+ endif
+ AS = $(CC) -c
endif
-AS = $(CC) -c
# -dumpversion in gcc-2.91 shows "egcs-2.91.66". In later version, it only
# prints the numbers (e.g. "2.95", "3.2.1")
@@ -261,9 +266,3 @@ endif
ifdef MINIMIZE_RAM_USAGE
CFLAGS += -DMINIMIZE_RAM_USAGE
endif
-
-ifdef CROSS_COMPILE_ARCH
- STRIP = $(ALT_COMPILER_PATH)/strip
-else
- STRIP = strip
-endif
diff --git a/make/linux/makefiles/sparcWorks.make b/make/linux/makefiles/sparcWorks.make
index 81de9c33b..c87f50440 100644
--- a/make/linux/makefiles/sparcWorks.make
+++ b/make/linux/makefiles/sparcWorks.make
@@ -25,12 +25,15 @@
#------------------------------------------------------------------------
# CC, CXX & AS
-CXX = CC
-CC = cc
-AS = $(CC) -c
-
-HOSTCXX = $(CXX)
-HOSTCC = $(CC)
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+ CXX = CC
+ CC = cc
+ AS = $(CC) -c
+
+ HOSTCXX = $(CXX)
+ HOSTCC = $(CC)
+endif
ARCHFLAG = $(ARCHFLAG/$(BUILDARCH))
ARCHFLAG/i486 = -m32
diff --git a/make/solaris/makefiles/buildtree.make b/make/solaris/makefiles/buildtree.make
index 129a48494..901100fb7 100644
--- a/make/solaris/makefiles/buildtree.make
+++ b/make/solaris/makefiles/buildtree.make
@@ -55,6 +55,7 @@
# The makefiles are split this way so that "make foo" will run faster by not
# having to read the dependency files for the vm.
+-include $(SPEC)
include $(GAMMADIR)/make/scm.make
include $(GAMMADIR)/make/altsrc.make
@@ -237,6 +238,8 @@ flags.make: $(BUILDTREE_MAKE) ../shared_dirs.lst
echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
echo "SYSDEFS += \$$(HOTSPOT_EXTRA_SYSDEFS)"; \
echo; \
+ [ -n "$(SPEC)" ] && \
+ echo "include $(SPEC)"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(VARIANT).make"; \
echo "include \$$(GAMMADIR)/make/$(OS_FAMILY)/makefiles/$(COMPILER).make"; \
) > $@
diff --git a/make/solaris/makefiles/gcc.make b/make/solaris/makefiles/gcc.make
index d4c54abd2..4d0db9e7a 100644
--- a/make/solaris/makefiles/gcc.make
+++ b/make/solaris/makefiles/gcc.make
@@ -25,9 +25,13 @@
#------------------------------------------------------------------------
# CC, CXX & AS
-CXX = g++
-CC = gcc
-AS = $(CC) -c
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+ CXX = g++
+ CC = gcc
+ AS = $(CC) -c
+ MCS = /usr/ccs/bin/mcs
+endif
Compiler = gcc
@@ -193,5 +197,3 @@ DEBUG_CFLAGS += $(DEBUG_CFLAGS/$(BUILDARCH))
ifeq ($(DEBUG_CFLAGS/$(BUILDARCH)),)
DEBUG_CFLAGS += -gstabs
endif
-
-MCS = /usr/ccs/bin/mcs
diff --git a/make/solaris/makefiles/sparcWorks.make b/make/solaris/makefiles/sparcWorks.make
index 8baf3c1d4..8ef47c563 100644
--- a/make/solaris/makefiles/sparcWorks.make
+++ b/make/solaris/makefiles/sparcWorks.make
@@ -22,18 +22,22 @@
#
#
-# Compiler-specific flags for sparcworks.
+# If a SPEC is not set already, then use these defaults.
+ifeq ($(SPEC),)
+ # Compiler-specific flags for sparcworks.
+ CC = cc
+ CXX = CC
-# tell make which C and C++ compilers to use
-CC = cc
-CXX = CC
+ # Note that this 'as' is an older version of the Sun Studio 'fbe', and will
+ # use the older style options. The 'fbe' options will match 'cc' and 'CC'.
+ AS = /usr/ccs/bin/as
-# Note that this 'as' is an older version of the Sun Studio 'fbe', and will
-# use the older style options. The 'fbe' options will match 'cc' and 'CC'.
-AS = /usr/ccs/bin/as
+ NM = /usr/ccs/bin/nm
+ NAWK = /bin/nawk
-NM = /usr/ccs/bin/nm
-NAWK = /bin/nawk
+ MCS = /usr/ccs/bin/mcs
+ STRIP = /usr/ccs/bin/strip
+endif
REORDER_FLAG = -xF
@@ -557,9 +561,6 @@ else
#LINK_INTO = LIBJVM
endif
-MCS = /usr/ccs/bin/mcs
-STRIP = /usr/ccs/bin/strip
-
# Solaris platforms collect lots of redundant file-ident lines,
# to the point of wasting a significant percentage of file space.
# (The text is stored in ELF .comment sections, contributed by
diff --git a/make/windows/build.make b/make/windows/build.make
index 8ec004d49..fff8a8530 100644
--- a/make/windows/build.make
+++ b/make/windows/build.make
@@ -297,6 +297,10 @@ $(variantDir)\local.make: checks
@ echo BUILDARCH=$(BUILDARCH) >> $@
@ echo Platform_arch=$(Platform_arch) >> $@
@ echo Platform_arch_model=$(Platform_arch_model) >> $@
+ @ echo CXX=$(CXX) >> $@
+ @ echo LD=$(LD) >> $@
+ @ echo MT=$(MT) >> $@
+ @ echo RC=$(RC) >> $@
@ sh $(WorkSpace)/make/windows/get_msc_ver.sh >> $@
checks: checkVariant checkWorkSpace checkSA
diff --git a/make/windows/makefiles/compile.make b/make/windows/makefiles/compile.make
index 1c9855c15..e1848a4ac 100644
--- a/make/windows/makefiles/compile.make
+++ b/make/windows/makefiles/compile.make
@@ -23,7 +23,9 @@
#
# Generic compiler settings
+!if "x$(CXX)" == "x"
CXX=cl.exe
+!endif
# CXX Flags: (these vary slightly from VC6->VS2003->VS2005 compilers)
# /nologo Supress copyright message at every cl.exe startup
@@ -183,8 +185,10 @@ BUFFEROVERFLOWLIB = bufferoverflowU.lib
LD_FLAGS = /manifest $(LD_FLAGS) $(BUFFEROVERFLOWLIB)
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
+!if "x$(MT)" == "x"
MT=mt.exe
!endif
+!endif
!if "$(COMPILER_NAME)" == "VS2008"
PRODUCT_OPT_OPTION = /O2 /Oy-
@@ -194,8 +198,10 @@ GX_OPTION = /EHsc
LD_FLAGS = /manifest $(LD_FLAGS)
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
+!if "x$(MT)" == "x"
MT=mt.exe
!endif
+!endif
!if "$(COMPILER_NAME)" == "VS2010"
PRODUCT_OPT_OPTION = /O2 /Oy-
@@ -205,7 +211,9 @@ GX_OPTION = /EHsc
LD_FLAGS = /manifest $(LD_FLAGS)
# Manifest Tool - used in VS2005 and later to adjust manifests stored
# as resources inside build artifacts.
+!if "x$(MT)" == "x"
MT=mt.exe
+!endif
!if "$(BUILDARCH)" == "i486"
LD_FLAGS = /SAFESEH $(LD_FLAGS)
!endif
@@ -225,7 +233,9 @@ FASTDEBUG_OPT_OPTION = $(DEBUG_OPT_OPTION)
!endif
# Generic linker settings
+!if "x$(LD)" == "x"
LD=link.exe
+!endif
LD_FLAGS= $(LD_FLAGS) kernel32.lib user32.lib gdi32.lib winspool.lib \
comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib \
uuid.lib Wsock32.lib winmm.lib /nologo /machine:$(MACHINE) /opt:REF \
@@ -237,7 +247,9 @@ LD_FLAGS= $(LD_FLAGS) psapi.lib
!endif
# Resource compiler settings
+!if "x$(RC)" == "x"
RC=rc.exe
+!endif
RC_FLAGS=/D "HS_VER=$(HS_VER)" \
/D "HS_DOTVER=$(HS_DOTVER)" \
/D "HS_BUILD_ID=$(HS_BUILD_ID)" \
diff --git a/make/windows/makefiles/defs.make b/make/windows/makefiles/defs.make
index c1be7d2c8..993799e37 100644
--- a/make/windows/makefiles/defs.make
+++ b/make/windows/makefiles/defs.make
@@ -202,3 +202,19 @@ ifeq ($(BUILD_WIN_SA), 1)
# Must pass this down to nmake.
MAKE_ARGS += BUILD_WIN_SA=1
endif
+
+# Propagate compiler and tools paths from configure to nmake.
+# Need to make sure they contain \\ and not /.
+ifneq ($(SPEC),)
+ ifeq ($(USING_CYGWIN), true)
+ MAKE_ARGS += CXX="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(CXX)))"
+ MAKE_ARGS += LD="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(LD)))"
+ MAKE_ARGS += RC="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(RC)))"
+ MAKE_ARGS += MT="$(subst /,\\,$(shell /bin/cygpath -s -m -a $(MT)))"
+ else
+ MAKE_ARGS += CXX="$(subst /,\\,$(CXX))"
+ MAKE_ARGS += LD="$(subst /,\\,$(LD))"
+ MAKE_ARGS += RC="$(subst /,\\,$(RC))"
+ MAKE_ARGS += MT="$(subst /,\\,$(MT))"
+ endif
+endif
diff --git a/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/src/cpu/x86/vm/c1_Runtime1_x86.cpp
index 5f2cf3886..30df6087d 100644
--- a/src/cpu/x86/vm/c1_Runtime1_x86.cpp
+++ b/src/cpu/x86/vm/c1_Runtime1_x86.cpp
@@ -47,6 +47,12 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e
assert(!(oop_result1->is_valid() || oop_result2->is_valid()) || oop_result1 != oop_result2, "registers must be different");
assert(oop_result1 != thread && oop_result2 != thread, "registers must be different");
assert(args_size >= 0, "illegal args_size");
+ bool align_stack = false;
+#ifdef _LP64
+ // At a method handle call, the stack may not be properly aligned
+ // when returning with an exception.
+ align_stack = (stub_id() == Runtime1::handle_exception_from_callee_id);
+#endif
#ifdef _LP64
mov(c_rarg0, thread);
@@ -59,11 +65,21 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e
push(thread);
#endif // _LP64
- set_last_Java_frame(thread, noreg, rbp, NULL);
+ int call_offset;
+ if (!align_stack) {
+ set_last_Java_frame(thread, noreg, rbp, NULL);
+ } else {
+ address the_pc = pc();
+ call_offset = offset();
+ set_last_Java_frame(thread, noreg, rbp, the_pc);
+ andptr(rsp, -(StackAlignmentInBytes)); // Align stack
+ }
// do the call
call(RuntimeAddress(entry));
- int call_offset = offset();
+ if (!align_stack) {
+ call_offset = offset();
+ }
// verify callee-saved register
#ifdef ASSERT
guarantee(thread != rax, "change this code");
@@ -78,7 +94,7 @@ int StubAssembler::call_RT(Register oop_result1, Register oop_result2, address e
}
pop(rax);
#endif
- reset_last_Java_frame(thread, true, false);
+ reset_last_Java_frame(thread, true, align_stack);
// discard thread and arguments
NOT_LP64(addptr(rsp, num_rt_args()*BytesPerWord));
diff --git a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
index b7af4544d..68a23939d 100644
--- a/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
+++ b/src/cpu/x86/vm/sharedRuntime_x86_64.cpp
@@ -1181,14 +1181,13 @@ static void save_or_restore_arguments(MacroAssembler* masm,
BasicType* in_sig_bt) {
// if map is non-NULL then the code should store the values,
// otherwise it should load them.
- int handle_index = 0;
+ int slot = arg_save_area;
// Save down double word first
for ( int i = 0; i < total_in_args; i++) {
if (in_regs[i].first()->is_XMMRegister() && in_sig_bt[i] == T_DOUBLE) {
- int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area;
int offset = slot * VMRegImpl::stack_slot_size;
- handle_index += 2;
- assert(handle_index <= stack_slots, "overflow");
+ slot += VMRegImpl::slots_per_word;
+ assert(slot <= stack_slots, "overflow");
if (map != NULL) {
__ movdbl(Address(rsp, offset), in_regs[i].first()->as_XMMRegister());
} else {
@@ -1197,10 +1196,7 @@ static void save_or_restore_arguments(MacroAssembler* masm,
}
if (in_regs[i].first()->is_Register() &&
(in_sig_bt[i] == T_LONG || in_sig_bt[i] == T_ARRAY)) {
- int slot = handle_index * VMRegImpl::slots_per_word + arg_save_area;
int offset = slot * VMRegImpl::stack_slot_size;
- handle_index += 2;
- assert(handle_index <= stack_slots, "overflow");
if (map != NULL) {
__ movq(Address(rsp, offset), in_regs[i].first()->as_Register());
if (in_sig_bt[i] == T_ARRAY) {
@@ -1209,14 +1205,15 @@ static void save_or_restore_arguments(MacroAssembler* masm,
} else {
__ movq(in_regs[i].first()->as_Register(), Address(rsp, offset));
}
+ slot += VMRegImpl::slots_per_word;
}
}
// Save or restore single word registers
for ( int i = 0; i < total_in_args; i++) {
if (in_regs[i].first()->is_Register()) {
- int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area;
int offset = slot * VMRegImpl::stack_slot_size;
- assert(handle_index <= stack_slots, "overflow");
+ slot++;
+ assert(slot <= stack_slots, "overflow");
// Value is in an input register pass we must flush it to the stack
const Register reg = in_regs[i].first()->as_Register();
@@ -1241,9 +1238,9 @@ static void save_or_restore_arguments(MacroAssembler* masm,
}
} else if (in_regs[i].first()->is_XMMRegister()) {
if (in_sig_bt[i] == T_FLOAT) {
- int slot = handle_index++ * VMRegImpl::slots_per_word + arg_save_area;
int offset = slot * VMRegImpl::stack_slot_size;
- assert(handle_index <= stack_slots, "overflow");
+ slot++;
+ assert(slot <= stack_slots, "overflow");
if (map != NULL) {
__ movflt(Address(rsp, offset), in_regs[i].first()->as_XMMRegister());
} else {
@@ -1368,6 +1365,174 @@ static void unpack_array_argument(MacroAssembler* masm, VMRegPair reg, BasicType
__ bind(done);
}
+
+class ComputeMoveOrder: public StackObj {
+ class MoveOperation: public ResourceObj {
+ friend class ComputeMoveOrder;
+ private:
+ VMRegPair _src;
+ VMRegPair _dst;
+ int _src_index;
+ int _dst_index;
+ bool _processed;
+ MoveOperation* _next;
+ MoveOperation* _prev;
+
+ static int get_id(VMRegPair r) {
+ return r.first()->value();
+ }
+
+ public:
+ MoveOperation(int src_index, VMRegPair src, int dst_index, VMRegPair dst):
+ _src(src)
+ , _src_index(src_index)
+ , _dst(dst)
+ , _dst_index(dst_index)
+ , _next(NULL)
+ , _prev(NULL)
+ , _processed(false) {
+ }
+
+ VMRegPair src() const { return _src; }
+ int src_id() const { return get_id(src()); }
+ int src_index() const { return _src_index; }
+ VMRegPair dst() const { return _dst; }
+ void set_dst(int i, VMRegPair dst) { _dst_index = i, _dst = dst; }
+ int dst_index() const { return _dst_index; }
+ int dst_id() const { return get_id(dst()); }
+ MoveOperation* next() const { return _next; }
+ MoveOperation* prev() const { return _prev; }
+ void set_processed() { _processed = true; }
+ bool is_processed() const { return _processed; }
+
+ // insert
+ void break_cycle(VMRegPair temp_register) {
+ // create a new store following the last store
+ // to move from the temp_register to the original
+ MoveOperation* new_store = new MoveOperation(-1, temp_register, dst_index(), dst());
+
+ // break the cycle of links and insert new_store at the end
+ // break the reverse link.
+ MoveOperation* p = prev();
+ assert(p->next() == this, "must be");
+ _prev = NULL;
+ p->_next = new_store;
+ new_store->_prev = p;
+
+ // change the original store to save it's value in the temp.
+ set_dst(-1, temp_register);
+ }
+
+ void link(GrowableArray<MoveOperation*>& killer) {
+ // link this store in front the store that it depends on
+ MoveOperation* n = killer.at_grow(src_id(), NULL);
+ if (n != NULL) {
+ assert(_next == NULL && n->_prev == NULL, "shouldn't have been set yet");
+ _next = n;
+ n->_prev = this;
+ }
+ }
+ };
+
+ private:
+ GrowableArray<MoveOperation*> edges;
+
+ public:
+ ComputeMoveOrder(int total_in_args, VMRegPair* in_regs, int total_c_args, VMRegPair* out_regs,
+ BasicType* in_sig_bt, GrowableArray<int>& arg_order, VMRegPair tmp_vmreg) {
+ // Move operations where the dest is the stack can all be
+ // scheduled first since they can't interfere with the other moves.
+ for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
+ if (in_sig_bt[i] == T_ARRAY) {
+ c_arg--;
+ if (out_regs[c_arg].first()->is_stack() &&
+ out_regs[c_arg + 1].first()->is_stack()) {
+ arg_order.push(i);
+ arg_order.push(c_arg);
+ } else {
+ if (out_regs[c_arg].first()->is_stack() ||
+ in_regs[i].first() == out_regs[c_arg].first()) {
+ add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg + 1]);
+ } else {
+ add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg]);
+ }
+ }
+ } else if (in_sig_bt[i] == T_VOID) {
+ arg_order.push(i);
+ arg_order.push(c_arg);
+ } else {
+ if (out_regs[c_arg].first()->is_stack() ||
+ in_regs[i].first() == out_regs[c_arg].first()) {
+ arg_order.push(i);
+ arg_order.push(c_arg);
+ } else {
+ add_edge(i, in_regs[i].first(), c_arg, out_regs[c_arg]);
+ }
+ }
+ }
+ // Break any cycles in the register moves and emit the in the
+ // proper order.
+ GrowableArray<MoveOperation*>* stores = get_store_order(tmp_vmreg);
+ for (int i = 0; i < stores->length(); i++) {
+ arg_order.push(stores->at(i)->src_index());
+ arg_order.push(stores->at(i)->dst_index());
+ }
+ }
+
+ // Collected all the move operations
+ void add_edge(int src_index, VMRegPair src, int dst_index, VMRegPair dst) {
+ if (src.first() == dst.first()) return;
+ edges.append(new MoveOperation(src_index, src, dst_index, dst));
+ }
+
+ // Walk the edges breaking cycles between moves. The result list
+ // can be walked in order to produce the proper set of loads
+ GrowableArray<MoveOperation*>* get_store_order(VMRegPair temp_register) {
+ // Record which moves kill which values
+ GrowableArray<MoveOperation*> killer;
+ for (int i = 0; i < edges.length(); i++) {
+ MoveOperation* s = edges.at(i);
+ assert(killer.at_grow(s->dst_id(), NULL) == NULL, "only one killer");
+ killer.at_put_grow(s->dst_id(), s, NULL);
+ }
+ assert(killer.at_grow(MoveOperation::get_id(temp_register), NULL) == NULL,
+ "make sure temp isn't in the registers that are killed");
+
+ // create links between loads and stores
+ for (int i = 0; i < edges.length(); i++) {
+ edges.at(i)->link(killer);
+ }
+
+ // at this point, all the move operations are chained together
+ // in a doubly linked list. Processing it backwards finds
+ // the beginning of the chain, forwards finds the end. If there's
+ // a cycle it can be broken at any point, so pick an edge and walk
+ // backward until the list ends or we end where we started.
+ GrowableArray<MoveOperation*>* stores = new GrowableArray<MoveOperation*>();
+ for (int e = 0; e < edges.length(); e++) {
+ MoveOperation* s = edges.at(e);
+ if (!s->is_processed()) {
+ MoveOperation* start = s;
+ // search for the beginning of the chain or cycle
+ while (start->prev() != NULL && start->prev() != s) {
+ start = start->prev();
+ }
+ if (start->prev() == s) {
+ start->break_cycle(temp_register);
+ }
+ // walk the chain forward inserting to store list
+ while (start != NULL) {
+ stores->append(start);
+ start->set_processed();
+ start = start->next();
+ }
+ }
+ }
+ return stores;
+ }
+};
+
+
// ---------------------------------------------------------------------------
// Generate a native wrapper for a given method. The method takes arguments
// in the Java compiled code convention, marshals them to the native
@@ -1488,12 +1653,12 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
if (in_regs[i].first()->is_Register()) {
const Register reg = in_regs[i].first()->as_Register();
switch (in_sig_bt[i]) {
- case T_ARRAY:
case T_BOOLEAN:
case T_BYTE:
case T_SHORT:
case T_CHAR:
case T_INT: single_slots++; break;
+ case T_ARRAY:
case T_LONG: double_slots++; break;
default: ShouldNotReachHere();
}
@@ -1690,36 +1855,43 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
#endif /* ASSERT */
- if (is_critical_native) {
- // The mapping of Java and C arguments passed in registers are
- // rotated by one, which helps when passing arguments to regular
- // Java method but for critical natives that creates a cycle which
- // can cause arguments to be killed before they are used. Break
- // the cycle by moving the first argument into a temporary
- // register.
- for (int i = 0; i < total_c_args; i++) {
- if (in_regs[i].first()->is_Register() &&
- in_regs[i].first()->as_Register() == rdi) {
- __ mov(rbx, rdi);
- in_regs[i].set1(rbx->as_VMReg());
- }
- }
- }
-
// This may iterate in two different directions depending on the
// kind of native it is. The reason is that for regular JNI natives
// the incoming and outgoing registers are offset upwards and for
// critical natives they are offset down.
- int c_arg = total_c_args - 1;
- int stride = -1;
- int init = total_in_args - 1;
- if (is_critical_native) {
- // stride forwards
- c_arg = 0;
- stride = 1;
- init = 0;
- }
- for (int i = init, count = 0; count < total_in_args; i += stride, c_arg += stride, count++ ) {
+ GrowableArray<int> arg_order(2 * total_in_args);
+ VMRegPair tmp_vmreg;
+ tmp_vmreg.set1(rbx->as_VMReg());
+
+ if (!is_critical_native) {
+ for (int i = total_in_args - 1, c_arg = total_c_args - 1; i >= 0; i--, c_arg--) {
+ arg_order.push(i);
+ arg_order.push(c_arg);
+ }
+ } else {
+ // Compute a valid move order, using tmp_vmreg to break any cycles
+ ComputeMoveOrder cmo(total_in_args, in_regs, total_c_args, out_regs, in_sig_bt, arg_order, tmp_vmreg);
+ }
+
+ int temploc = -1;
+ for (int ai = 0; ai < arg_order.length(); ai += 2) {
+ int i = arg_order.at(ai);
+ int c_arg = arg_order.at(ai + 1);
+ __ block_comment(err_msg("move %d -> %d", i, c_arg));
+ if (c_arg == -1) {
+ assert(is_critical_native, "should only be required for critical natives");
+ // This arg needs to be moved to a temporary
+ __ mov(tmp_vmreg.first()->as_Register(), in_regs[i].first()->as_Register());
+ in_regs[i] = tmp_vmreg;
+ temploc = i;
+ continue;
+ } else if (i == -1) {
+ assert(is_critical_native, "should only be required for critical natives");
+ // Read from the temporary location
+ assert(temploc != -1, "must be valid");
+ i = temploc;
+ temploc = -1;
+ }
#ifdef ASSERT
if (in_regs[i].first()->is_Register()) {
assert(!reg_destroyed[in_regs[i].first()->as_Register()->encoding()], "destroyed reg!");
@@ -1779,7 +1951,7 @@ nmethod *SharedRuntime::generate_native_wrapper(MacroAssembler *masm,
// point c_arg at the first arg that is already loaded in case we
// need to spill before we call out
- c_arg++;
+ int c_arg = total_c_args - total_in_args;
// Pre-load a static method's oop into r14. Used both by locking code and
// the normal JNI call code.
@@ -3620,8 +3792,12 @@ void OptoRuntime::generate_exception_blob() {
//
// address OptoRuntime::handle_exception_C(JavaThread* thread)
- __ set_last_Java_frame(noreg, noreg, NULL);
+ // At a method handle call, the stack may not be properly aligned
+ // when returning with an exception.
+ address the_pc = __ pc();
+ __ set_last_Java_frame(noreg, noreg, the_pc);
__ mov(c_rarg0, r15_thread);
+ __ andptr(rsp, -(StackAlignmentInBytes)); // Align stack
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, OptoRuntime::handle_exception_C)));
// Set an oopmap for the call site. This oopmap will only be used if we
@@ -3632,9 +3808,9 @@ void OptoRuntime::generate_exception_blob() {
OopMapSet* oop_maps = new OopMapSet();
- oop_maps->add_gc_map( __ pc()-start, new OopMap(SimpleRuntimeFrame::framesize, 0));
+ oop_maps->add_gc_map(the_pc - start, new OopMap(SimpleRuntimeFrame::framesize, 0));
- __ reset_last_Java_frame(false, false);
+ __ reset_last_Java_frame(false, true);
// Restore callee-saved registers
diff --git a/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
index d68bdac6d..9d9472200 100644
--- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp
+++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp
@@ -710,6 +710,21 @@ class StubGenerator: public StubCodeGenerator {
return start;
}
+ // Support for intptr_t get_previous_sp()
+ //
+ // This routine is used to find the previous stack pointer for the
+ // caller.
+ address generate_get_previous_sp() {
+ StubCodeMark mark(this, "StubRoutines", "get_previous_sp");
+ address start = __ pc();
+
+ __ movptr(rax, rsp);
+ __ addptr(rax, 8); // return address is at the top of the stack.
+ __ ret(0);
+
+ return start;
+ }
+
//----------------------------------------------------------------------------------------------------
// Support for void verify_mxcsr()
//
@@ -3060,6 +3075,7 @@ class StubGenerator: public StubCodeGenerator {
// platform dependent
StubRoutines::x86::_get_previous_fp_entry = generate_get_previous_fp();
+ StubRoutines::x86::_get_previous_sp_entry = generate_get_previous_sp();
StubRoutines::x86::_verify_mxcsr_entry = generate_verify_mxcsr();
diff --git a/src/cpu/x86/vm/stubRoutines_x86_64.cpp b/src/cpu/x86/vm/stubRoutines_x86_64.cpp
index 182872b88..782dc9063 100644
--- a/src/cpu/x86/vm/stubRoutines_x86_64.cpp
+++ b/src/cpu/x86/vm/stubRoutines_x86_64.cpp
@@ -43,6 +43,7 @@
// a description of how to extend it, see the stubRoutines.hpp file.
address StubRoutines::x86::_get_previous_fp_entry = NULL;
+address StubRoutines::x86::_get_previous_sp_entry = NULL;
address StubRoutines::x86::_verify_mxcsr_entry = NULL;
diff --git a/src/cpu/x86/vm/stubRoutines_x86_64.hpp b/src/cpu/x86/vm/stubRoutines_x86_64.hpp
index 3d2a4fb9a..7737c4eee 100644
--- a/src/cpu/x86/vm/stubRoutines_x86_64.hpp
+++ b/src/cpu/x86/vm/stubRoutines_x86_64.hpp
@@ -41,6 +41,7 @@ class x86 {
private:
static address _get_previous_fp_entry;
+ static address _get_previous_sp_entry;
static address _verify_mxcsr_entry;
static address _f2i_fixup;
@@ -61,6 +62,11 @@ class x86 {
return _get_previous_fp_entry;
}
+ static address get_previous_sp_entry()
+ {
+ return _get_previous_sp_entry;
+ }
+
static address verify_mxcsr_entry()
{
return _verify_mxcsr_entry;
diff --git a/src/os/linux/vm/os_linux.cpp b/src/os/linux/vm/os_linux.cpp
index 72f3fd07a..6a33c0e80 100644
--- a/src/os/linux/vm/os_linux.cpp
+++ b/src/os/linux/vm/os_linux.cpp
@@ -4690,14 +4690,12 @@ char* os::map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
int prot;
- int flags;
+ int flags = MAP_PRIVATE;
if (read_only) {
prot = PROT_READ;
- flags = MAP_SHARED;
} else {
prot = PROT_READ | PROT_WRITE;
- flags = MAP_PRIVATE;
}
if (allow_exec) {
diff --git a/src/os/solaris/vm/os_solaris.cpp b/src/os/solaris/vm/os_solaris.cpp
index c47d37433..31bd41862 100644
--- a/src/os/solaris/vm/os_solaris.cpp
+++ b/src/os/solaris/vm/os_solaris.cpp
@@ -1013,15 +1013,6 @@ extern "C" void breakpoint() {
// use debugger to set breakpoint here
}
-// Returns an estimate of the current stack pointer. Result must be guaranteed to
-// point into the calling threads stack, and be no lower than the current stack
-// pointer.
-address os::current_stack_pointer() {
- volatile int dummy;
- address sp = (address)&dummy + 8; // %%%% need to confirm if this is right
- return sp;
-}
-
static thread_t main_thread;
// Thread start routine for all new Java threads
diff --git a/src/os/windows/vm/os_windows.cpp b/src/os/windows/vm/os_windows.cpp
index 970aab747..de38c6c12 100644
--- a/src/os/windows/vm/os_windows.cpp
+++ b/src/os/windows/vm/os_windows.cpp
@@ -324,16 +324,6 @@ extern "C" void breakpoint() {
os::breakpoint();
}
-// Returns an estimate of the current stack pointer. Result must be guaranteed
-// to point into the calling threads stack, and be no lower than the current
-// stack pointer.
-
-address os::current_stack_pointer() {
- int dummy;
- address sp = (address)&dummy;
- return sp;
-}
-
// os::current_stack_base()
//
// Returns the base of the stack, which is the stack's
diff --git a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
index 06ba58075..12d6871ca 100644
--- a/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
+++ b/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp
@@ -1126,3 +1126,8 @@ void os::setup_fpu() {
: "r" (fpu_cntrl) : "memory");
#endif // !AMD64
}
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
diff --git a/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp b/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
index ff5b32dbf..4bb5a8abb 100644
--- a/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
+++ b/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp
@@ -562,3 +562,8 @@ extern "C" {
}
};
#endif // !_LP64
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
diff --git a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
index 62131ee6f..11c90e522 100644
--- a/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
+++ b/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
@@ -756,3 +756,8 @@ size_t os::Linux::default_guard_size(os::ThreadType thr_type) {
// guard page, only enable glibc guard page for non-Java threads.
return (thr_type == java_thread ? 0 : page_size());
}
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
diff --git a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
index ba484b9fd..93bb1f459 100644
--- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
+++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
@@ -862,3 +862,11 @@ void os::setup_fpu() {
: "r" (fpu_cntrl) : "memory");
#endif // !AMD64
}
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+#ifdef AMD64
+ assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
+#endif
+}
+#endif
diff --git a/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
index 32c2d0a51..203090ce0 100644
--- a/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
+++ b/src/os_cpu/linux_zero/vm/os_linux_zero.cpp
@@ -506,3 +506,8 @@ extern "C" {
}
};
#endif // !_LP64
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
diff --git a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
index 971f600fe..752daf7bf 100644
--- a/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
+++ b/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp
@@ -251,6 +251,15 @@ frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
}
+// Returns an estimate of the current stack pointer. Result must be guaranteed to
+// point into the calling threads stack, and be no lower than the current stack
+// pointer.
+address os::current_stack_pointer() {
+ volatile int dummy;
+ address sp = (address)&dummy + 8; // %%%% need to confirm if this is right
+ return sp;
+}
+
frame os::current_frame() {
intptr_t* sp = StubRoutines::Sparc::flush_callers_register_windows_func()();
frame myframe(sp, frame::unpatchable,
@@ -815,3 +824,8 @@ add_func_t* os::atomic_add_func = os::atomic_add_bootstrap;
__asm__ __volatile__ ("wr %%g0, 0, %%fprs \n\t" : : :);
}
#endif //defined(__sparc) && defined(COMPILER2)
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+}
+#endif
diff --git a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
index 78e93ea66..ec047c16b 100644
--- a/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
+++ b/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp
@@ -237,6 +237,12 @@ frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
+extern "C" intptr_t *_get_current_sp(); // in .il file
+
+address os::current_stack_pointer() {
+ return (address)_get_current_sp();
+}
+
extern "C" intptr_t *_get_current_fp(); // in .il file
frame os::current_frame() {
@@ -954,3 +960,11 @@ void os::setup_fpu() {
_solaris_raw_setup_fpu(fpu_cntrl);
}
#endif // AMD64
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+#ifdef AMD64
+ assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
+#endif
+}
+#endif
diff --git a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il
index b635a8292..9b0f07da3 100644
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_32.il
+++ b/src/os_cpu/solaris_x86/vm/solaris_x86_32.il
@@ -37,6 +37,12 @@
movl %gs:0, %eax
.end
+ // Get current sp
+ .inline _get_current_sp,0
+ .volatile
+ movl %esp, %eax
+ .end
+
// Get current fp
.inline _get_current_fp,0
.volatile
diff --git a/src/os_cpu/solaris_x86/vm/solaris_x86_64.il b/src/os_cpu/solaris_x86/vm/solaris_x86_64.il
index fb7946b8c..89809bc54 100644
--- a/src/os_cpu/solaris_x86/vm/solaris_x86_64.il
+++ b/src/os_cpu/solaris_x86/vm/solaris_x86_64.il
@@ -30,6 +30,12 @@
movq %fs:0, %rax
.end
+ // Get current sp
+ .inline _get_current_sp,0
+ .volatile
+ movq %rsp, %rax
+ .end
+
// Get current fp
.inline _get_current_fp,0
.volatile
diff --git a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp
index 960ceab66..52fe243ee 100644
--- a/src/os_cpu/windows_x86/vm/os_windows_x86.cpp
+++ b/src/os_cpu/windows_x86/vm/os_windows_x86.cpp
@@ -370,6 +370,26 @@ frame os::get_sender_for_C_frame(frame* fr) {
return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
}
+#ifndef AMD64
+// Returns an estimate of the current stack pointer. Result must be guaranteed
+// to point into the calling threads stack, and be no lower than the current
+// stack pointer.
+address os::current_stack_pointer() {
+ int dummy;
+ address sp = (address)&dummy;
+ return sp;
+}
+#else
+// Returns the current stack pointer. Accurate value needed for
+// os::verify_stack_alignment().
+address os::current_stack_pointer() {
+ typedef address get_sp_func();
+ get_sp_func* func = CAST_TO_FN_PTR(get_sp_func*,
+ StubRoutines::x86::get_previous_sp_entry());
+ return (*func)();
+}
+#endif
+
#ifndef AMD64
intptr_t* _get_previous_fp() {
@@ -546,3 +566,11 @@ void os::setup_fpu() {
__asm fldcw fpu_cntrl_word;
#endif // !AMD64
}
+
+#ifndef PRODUCT
+void os::verify_stack_alignment() {
+#ifdef AMD64
+ assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment");
+#endif
+}
+#endif
diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java
index 73e59566e..861fe4437 100644
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/Compilation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -33,6 +33,7 @@ public class Compilation implements LogEvent {
private boolean osr;
private Method method;
private CallSite call = new CallSite();
+ private CallSite lateInlineCall = new CallSite();
private int osrBci;
private String icount;
private String bcount;
@@ -80,6 +81,13 @@ public class Compilation implements LogEvent {
sb.append(site);
sb.append("\n");
}
+ if (getLateInlineCall().getCalls() != null) {
+ sb.append("late inline:\n");
+ for (CallSite site : getLateInlineCall().getCalls()) {
+ sb.append(site);
+ sb.append("\n");
+ }
+ }
return sb.toString();
}
@@ -115,6 +123,12 @@ public class Compilation implements LogEvent {
site.print(stream, indent + 2);
}
}
+ if (printInlining && lateInlineCall.getCalls() != null) {
+ stream.println("late inline:");
+ for (CallSite site : lateInlineCall.getCalls()) {
+ site.print(stream, indent + 2);
+ }
+ }
}
}
@@ -215,7 +229,11 @@ public class Compilation implements LogEvent {
}
public void setMethod(Method method) {
- this.method = method;
+ // Don't change method if it is already set to avoid changing
+ // it by post parse inlining info.
+ if (getMethod() == null) {
+ this.method = method;
+ }
}
public CallSite getCall() {
@@ -226,6 +244,10 @@ public class Compilation implements LogEvent {
this.call = call;
}
+ public CallSite getLateInlineCall() {
+ return lateInlineCall;
+ }
+
public double getElapsedTime() {
return end - start;
}
diff --git a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java
index d864db0ff..dc0b7ab34 100644
--- a/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java
+++ b/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 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
@@ -146,6 +146,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
private CallSite site;
private Stack<Phase> phaseStack = new Stack<Phase>();
private UncommonTrapEvent currentTrap;
+ private Stack<CallSite> late_inline_scope;
long parseLong(String l) {
try {
@@ -302,6 +303,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
}
events.add(compile);
compiles.put(makeId(atts), compile);
+ site = compile.getCall();
} else if (qname.equals("type")) {
type(search(atts, "id"), search(atts, "name"));
} else if (qname.equals("bc")) {
@@ -360,12 +362,22 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
// uncommon trap inserted during parsing.
// ignore for now
}
+ } else if (qname.equals("late_inline")) {
+ late_inline_scope = new Stack<CallSite>();
+ site = new CallSite(-999, method(search(atts, "method")));
+ late_inline_scope.push(site);
} else if (qname.equals("jvms")) {
// <jvms bci='4' method='java/io/DataInputStream readChar ()C' bytes='40' count='5815' iicount='20815'/>
if (currentTrap != null) {
currentTrap.addJVMS(atts.getValue("method"), Integer.parseInt(atts.getValue("bci")));
+ } else if (late_inline_scope != null) {
+ bci = Integer.parseInt(search(atts, "bci"));
+ site = new CallSite(bci, method(search(atts, "method")));
+ late_inline_scope.push(site);
} else {
- // Ignore <eliminate_allocation type='667'> and <eliminate_lock lock='1'>
+ // Ignore <eliminate_allocation type='667'>,
+ // <eliminate_lock lock='1'>,
+ // <replace_string_concat arguments='2' string_alloc='0' multiple='0'>
}
} else if (qname.equals("nmethod")) {
String id = makeId(atts);
@@ -379,7 +391,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
Method m = method(search(atts, "method"));
if (scopes.size() == 0) {
compile.setMethod(m);
- scopes.push(compile.getCall());
+ scopes.push(site);
} else {
if (site.getMethod() == m) {
scopes.push(site);
@@ -393,7 +405,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
}
} else if (qname.equals("parse_done")) {
CallSite call = scopes.pop();
- call.setEndNodes(Integer.parseInt(search(atts, "nodes")));
+ call.setEndNodes(Integer.parseInt(search(atts, "nodes", "1")));
call.setTimeStamp(Double.parseDouble(search(atts, "stamp")));
scopes.push(call);
}
@@ -408,6 +420,43 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants
scopes.pop();
} else if (qname.equals("uncommon_trap")) {
currentTrap = null;
+ } else if (qname.equals("late_inline")) {
+ // Populate late inlining info.
+
+ // late_inline scopes are specified in reverse order:
+ // compiled method should be on top of stack.
+ CallSite caller = late_inline_scope.pop();
+ Method m = compile.getMethod();
+ if (m != caller.getMethod()) {
+ System.out.println(m);
+ System.out.println(caller.getMethod() + " bci: " + bci);
+ throw new InternalError("call site and late_inline info don't match");
+ }
+
+ // late_inline contains caller+bci info, convert it
+ // to bci+callee info used by LogCompilation.
+ site = compile.getLateInlineCall();
+ do {
+ bci = caller.getBci();
+ // Next inlined call.
+ caller = late_inline_scope.pop();
+ CallSite callee = new CallSite(bci, caller.getMethod());
+ site.add(callee);
+ site = callee;
+ } while (!late_inline_scope.empty());
+
+ if (caller.getBci() != -999) {
+ System.out.println(caller.getMethod());
+ throw new InternalError("broken late_inline info");
+ }
+ if (site.getMethod() != caller.getMethod()) {
+ System.out.println(site.getMethod());
+ System.out.println(caller.getMethod());
+ throw new InternalError("call site and late_inline info don't match");
+ }
+ // late_inline is followed by parse with scopes.size() == 0,
+ // 'site' will be pushed to scopes.
+ late_inline_scope = null;
} else if (qname.equals("task")) {
types.clear();
methods.clear();
diff --git a/src/share/vm/c1/c1_LinearScan.cpp b/src/share/vm/c1/c1_LinearScan.cpp
index aaae71d46..fede09fe8 100644
--- a/src/share/vm/c1/c1_LinearScan.cpp
+++ b/src/share/vm/c1/c1_LinearScan.cpp
@@ -1884,7 +1884,7 @@ void LinearScan::resolve_exception_entry(BlockBegin* block, MoveResolver &move_r
if (move_resolver.has_mappings()) {
// insert moves after first instruction
- move_resolver.set_insert_position(block->lir(), 1);
+ move_resolver.set_insert_position(block->lir(), 0);
move_resolver.resolve_and_append_moves();
}
}
diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp
index d6ed1def5..92c06342d 100644
--- a/src/share/vm/classfile/vmSymbols.hpp
+++ b/src/share/vm/classfile/vmSymbols.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -509,6 +509,9 @@
template(clear_name, "clear") \
template(trigger_method_signature, "(ILjava/lang/management/MemoryUsage;)V") \
template(startAgent_name, "startAgent") \
+ template(startRemoteAgent_name, "startRemoteManagementAgent") \
+ template(startLocalAgent_name, "startLocalManagementAgent") \
+ template(stopRemoteAgent_name, "stopRemoteManagementAgent") \
template(java_lang_management_ThreadInfo_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;)V") \
template(java_lang_management_ThreadInfo_with_locks_constructor_signature, "(Ljava/lang/Thread;ILjava/lang/Object;Ljava/lang/Thread;JJJJ[Ljava/lang/StackTraceElement;[Ljava/lang/Object;[I[Ljava/lang/Object;)V") \
template(long_long_long_long_void_signature, "(JJJJ)V") \
diff --git a/src/share/vm/oops/cpCacheOop.cpp b/src/share/vm/oops/cpCacheOop.cpp
index 678bc1327..8ebc99678 100644
--- a/src/share/vm/oops/cpCacheOop.cpp
+++ b/src/share/vm/oops/cpCacheOop.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -504,17 +504,17 @@ bool ConstantPoolCacheEntry::is_interesting_method_entry(klassOop k) {
void ConstantPoolCacheEntry::print(outputStream* st, int index) const {
// print separator
- if (index == 0) tty->print_cr(" -------------");
+ if (index == 0) st->print_cr(" -------------");
// print entry
- tty->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this);
+ st->print("%3d ("PTR_FORMAT") ", index, (intptr_t)this);
if (is_secondary_entry())
- tty->print_cr("[%5d|secondary]", main_entry_index());
+ st->print_cr("[%5d|secondary]", main_entry_index());
else
- tty->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
- tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)(oop)_f1);
- tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2);
- tty->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags);
- tty->print_cr(" -------------");
+ st->print_cr("[%02x|%02x|%5d]", bytecode_2(), bytecode_1(), constant_pool_index());
+ st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)(oop)_f1);
+ st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_f2);
+ st->print_cr(" [ "PTR_FORMAT"]", (intptr_t)_flags);
+ st->print_cr(" -------------");
}
void ConstantPoolCacheEntry::verify(outputStream* st) const {
diff --git a/src/share/vm/opto/connode.cpp b/src/share/vm/opto/connode.cpp
index 9a3b65031..7e072ff44 100644
--- a/src/share/vm/opto/connode.cpp
+++ b/src/share/vm/opto/connode.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -1051,6 +1051,7 @@ Node *ConvL2INode::Ideal(PhaseGVN *phase, bool can_reshape) {
//------------------------------Value------------------------------------------
const Type *CastX2PNode::Value( PhaseTransform *phase ) const {
const Type* t = phase->type(in(1));
+ if (t == Type::TOP) return Type::TOP;
if (t->base() == Type_X && t->singleton()) {
uintptr_t bits = (uintptr_t) t->is_intptr_t()->get_con();
if (bits == 0) return TypePtr::NULL_PTR;
@@ -1121,6 +1122,7 @@ Node *CastX2PNode::Identity( PhaseTransform *phase ) {
//------------------------------Value------------------------------------------
const Type *CastP2XNode::Value( PhaseTransform *phase ) const {
const Type* t = phase->type(in(1));
+ if (t == Type::TOP) return Type::TOP;
if (t->base() == Type::RawPtr && t->singleton()) {
uintptr_t bits = (uintptr_t) t->is_rawptr()->get_con();
return TypeX::make(bits);
diff --git a/src/share/vm/opto/escape.cpp b/src/share/vm/opto/escape.cpp
index 27fd8171a..d7c67e252 100644
--- a/src/share/vm/opto/escape.cpp
+++ b/src/share/vm/opto/escape.cpp
@@ -2035,40 +2035,14 @@ void ConnectionGraph::find_init_values(Node* alloc, VectorSet* visited, PhaseTra
Node* store = ini->find_captured_store(offset, type2aelembytes(ft), phase);
if (store != NULL && store->is_Store()) {
value = store->in(MemNode::ValueIn);
- } else if (ptn->edge_count() > 0) { // Are there oop stores?
- // Check for a store which follows allocation without branches.
+ } else {
+ // There could be initializing stores which follow allocation.
// For example, a volatile field store is not collected
- // by Initialize node. TODO: it would be nice to use idom() here.
- //
- // Search all references to the same field which use different
- // AddP nodes, for example, in the next case:
- //
- // Point p[] = new Point[1];
- // if ( x ) { p[0] = new Point(); p[0].x = x; }
- // if ( p[0] != null ) { y = p[0].x; } // has CastPP
+ // by Initialize node.
//
- for (uint next = ei; (next < ae_cnt) && (value == NULL); next++) {
- uint fpi = pta->edge_target(next); // Field (AddP)
- PointsToNode *ptf = ptnode_adr(fpi);
- if (ptf->offset() == offset) {
- Node* nf = ptf->_node;
- for (DUIterator_Fast imax, i = nf->fast_outs(imax); i < imax; i++) {
- store = nf->fast_out(i);
- if (store->is_Store() && store->in(0) != NULL) {
- Node* ctrl = store->in(0);
- while(!(ctrl == ini || ctrl == alloc || ctrl == NULL ||
- ctrl == C->root() || ctrl == C->top() || ctrl->is_Region() ||
- ctrl->is_IfTrue() || ctrl->is_IfFalse())) {
- ctrl = ctrl->in(0);
- }
- if (ctrl == ini || ctrl == alloc) {
- value = store->in(MemNode::ValueIn);
- break;
- }
- }
- }
- }
- }
+ // Need to check for dependent loads to separate such stores from
+ // stores which follow loads. For now, add initial value NULL so
+ // that compare pointers optimization works correctly.
}
}
if (value == NULL || value != ptnode_adr(value->_idx)->_node) {
diff --git a/src/share/vm/runtime/interfaceSupport.hpp b/src/share/vm/runtime/interfaceSupport.hpp
index e1001eea1..2875ee0eb 100644
--- a/src/share/vm/runtime/interfaceSupport.hpp
+++ b/src/share/vm/runtime/interfaceSupport.hpp
@@ -436,6 +436,7 @@ class RuntimeHistogramElement : public HistogramElement {
#define VM_LEAF_BASE(result_type, header) \
TRACE_CALL(result_type, header) \
debug_only(NoHandleMark __hm;) \
+ os::verify_stack_alignment(); \
/* begin of body */
@@ -445,6 +446,7 @@ class RuntimeHistogramElement : public HistogramElement {
TRACE_CALL(result_type, header) \
HandleMarkCleaner __hm(thread); \
Thread* THREAD = thread; \
+ os::verify_stack_alignment(); \
/* begin of body */
@@ -454,6 +456,7 @@ class RuntimeHistogramElement : public HistogramElement {
TRACE_CALL(result_type, header) \
debug_only(NoHandleMark __hm;) \
Thread* THREAD = thread; \
+ os::verify_stack_alignment(); \
/* begin of body */
diff --git a/src/share/vm/runtime/os.hpp b/src/share/vm/runtime/os.hpp
index e77f3ce91..dd163e9a9 100644
--- a/src/share/vm/runtime/os.hpp
+++ b/src/share/vm/runtime/os.hpp
@@ -404,6 +404,8 @@ class os: AllStatic {
static address current_stack_base();
static size_t current_stack_size();
+ static void verify_stack_alignment() PRODUCT_RETURN;
+
static int message_box(const char* title, const char* message);
static char* do_you_want_to_debug(const char* message);
diff --git a/src/share/vm/services/diagnosticCommand.cpp b/src/share/vm/services/diagnosticCommand.cpp
index 78f4c2239..107b1abe5 100644
--- a/src/share/vm/services/diagnosticCommand.cpp
+++ b/src/share/vm/services/diagnosticCommand.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -49,6 +49,11 @@ void DCmdRegistrant::register_dcmds(){
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ClassHistogramDCmd>(true, false));
DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<ThreadDumpDCmd>(true, false));
+ //Enhanced JMX Agent Support
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartRemoteDCmd>(true,false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStartLocalDCmd>(true,false));
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<JMXStopRemoteDCmd>(true,false));
+
}
#ifndef HAVE_EXTRA_DCMD
@@ -344,3 +349,185 @@ int ThreadDumpDCmd::num_arguments() {
return 0;
}
}
+
+// Enhanced JMX Agent support
+
+JMXStartRemoteDCmd::JMXStartRemoteDCmd(outputStream *output, bool heap_allocated) :
+
+ DCmdWithParser(output, heap_allocated),
+
+ _config_file
+ ("config.file",
+ "set com.sun.management.config.file", "STRING", false),
+
+ _jmxremote_port
+ ("jmxremote.port",
+ "set com.sun.management.jmxremote.port", "STRING", false),
+
+ _jmxremote_rmi_port
+ ("jmxremote.rmi.port",
+ "set com.sun.management.jmxremote.rmi.port", "STRING", false),
+
+ _jmxremote_ssl
+ ("jmxremote.ssl",
+ "set com.sun.management.jmxremote.ssl", "STRING", false),
+
+ _jmxremote_registry_ssl
+ ("jmxremote.registry.ssl",
+ "set com.sun.management.jmxremote.registry.ssl", "STRING", false),
+
+ _jmxremote_authenticate
+ ("jmxremote.authenticate",
+ "set com.sun.management.jmxremote.authenticate", "STRING", false),
+
+ _jmxremote_password_file
+ ("jmxremote.password.file",
+ "set com.sun.management.jmxremote.password.file", "STRING", false),
+
+ _jmxremote_access_file
+ ("jmxremote.access.file",
+ "set com.sun.management.jmxremote.access.file", "STRING", false),
+
+ _jmxremote_login_config
+ ("jmxremote.login.config",
+ "set com.sun.management.jmxremote.login.config", "STRING", false),
+
+ _jmxremote_ssl_enabled_cipher_suites
+ ("jmxremote.ssl.enabled.cipher.suites",
+ "set com.sun.management.jmxremote.ssl.enabled.cipher.suite", "STRING", false),
+
+ _jmxremote_ssl_enabled_protocols
+ ("jmxremote.ssl.enabled.protocols",
+ "set com.sun.management.jmxremote.ssl.enabled.protocols", "STRING", false),
+
+ _jmxremote_ssl_need_client_auth
+ ("jmxremote.ssl.need.client.auth",
+ "set com.sun.management.jmxremote.need.client.auth", "STRING", false),
+
+ _jmxremote_ssl_config_file
+ ("jmxremote.ssl.config.file",
+ "set com.sun.management.jmxremote.ssl_config_file", "STRING", false)
+
+ {
+ _dcmdparser.add_dcmd_option(&_config_file);
+ _dcmdparser.add_dcmd_option(&_jmxremote_port);
+ _dcmdparser.add_dcmd_option(&_jmxremote_rmi_port);
+ _dcmdparser.add_dcmd_option(&_jmxremote_ssl);
+ _dcmdparser.add_dcmd_option(&_jmxremote_registry_ssl);
+ _dcmdparser.add_dcmd_option(&_jmxremote_authenticate);
+ _dcmdparser.add_dcmd_option(&_jmxremote_password_file);
+ _dcmdparser.add_dcmd_option(&_jmxremote_access_file);
+ _dcmdparser.add_dcmd_option(&_jmxremote_login_config);
+ _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_cipher_suites);
+ _dcmdparser.add_dcmd_option(&_jmxremote_ssl_enabled_protocols);
+ _dcmdparser.add_dcmd_option(&_jmxremote_ssl_need_client_auth);
+ _dcmdparser.add_dcmd_option(&_jmxremote_ssl_config_file);
+}
+
+
+int JMXStartRemoteDCmd::num_arguments() {
+ ResourceMark rm;
+ JMXStartRemoteDCmd* dcmd = new JMXStartRemoteDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+
+
+void JMXStartRemoteDCmd::execute(TRAPS) {
+ ResourceMark rm(THREAD);
+ HandleMark hm(THREAD);
+
+ // Load and initialize the sun.management.Agent class
+ // invoke startRemoteManagementAgent(string) method to start
+ // the remote management server.
+ // throw java.lang.NoSuchMethodError if the method doesn't exist
+
+ Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
+ klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+ instanceKlassHandle ik (THREAD, k);
+
+ JavaValue result(T_VOID);
+
+ // Pass all command line arguments to java as key=value,...
+ // All checks are done on java side
+
+ int len = 0;
+ stringStream options;
+ char comma[2] = {0,0};
+
+ // Leave default values on Agent.class side and pass only
+ // agruments explicitly set by user. All arguments passed
+ // to jcmd override properties with the same name set by
+ // command line with -D or by managmenent.properties
+ // file.
+#define PUT_OPTION(a) \
+ if ( (a).is_set() ){ \
+ options.print("%scom.sun.management.%s=%s", comma, (a).name(), (a).value()); \
+ comma[0] = ','; \
+ }
+
+ PUT_OPTION(_config_file);
+ PUT_OPTION(_jmxremote_port);
+ PUT_OPTION(_jmxremote_rmi_port);
+ PUT_OPTION(_jmxremote_ssl);
+ PUT_OPTION(_jmxremote_registry_ssl);
+ PUT_OPTION(_jmxremote_authenticate);
+ PUT_OPTION(_jmxremote_password_file);
+ PUT_OPTION(_jmxremote_access_file);
+ PUT_OPTION(_jmxremote_login_config);
+ PUT_OPTION(_jmxremote_ssl_enabled_cipher_suites);
+ PUT_OPTION(_jmxremote_ssl_enabled_protocols);
+ PUT_OPTION(_jmxremote_ssl_need_client_auth);
+ PUT_OPTION(_jmxremote_ssl_config_file);
+
+#undef PUT_OPTION
+
+ Handle str = java_lang_String::create_from_str(options.as_string(), CHECK);
+ JavaCalls::call_static(&result, ik, vmSymbols::startRemoteAgent_name(), vmSymbols::string_void_signature(), str, CHECK);
+}
+
+JMXStartLocalDCmd::JMXStartLocalDCmd(outputStream *output, bool heap_allocated) :
+ DCmd(output, heap_allocated)
+{
+ // do nothing
+}
+
+void JMXStartLocalDCmd::execute(TRAPS) {
+ ResourceMark rm(THREAD);
+ HandleMark hm(THREAD);
+
+ // Load and initialize the sun.management.Agent class
+ // invoke startLocalManagementAgent(void) method to start
+ // the local management server
+ // throw java.lang.NoSuchMethodError if method doesn't exist
+
+ Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
+ klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+ instanceKlassHandle ik (THREAD, k);
+
+ JavaValue result(T_VOID);
+ JavaCalls::call_static(&result, ik, vmSymbols::startLocalAgent_name(), vmSymbols::void_method_signature(), CHECK);
+}
+
+
+void JMXStopRemoteDCmd::execute(TRAPS) {
+ ResourceMark rm(THREAD);
+ HandleMark hm(THREAD);
+
+ // Load and initialize the sun.management.Agent class
+ // invoke stopRemoteManagementAgent method to stop the
+ // management server
+ // throw java.lang.NoSuchMethodError if method doesn't exist
+
+ Handle loader = Handle(THREAD, SystemDictionary::java_system_loader());
+ klassOop k = SystemDictionary::resolve_or_fail(vmSymbols::sun_management_Agent(), loader, Handle(), true, CHECK);
+ instanceKlassHandle ik (THREAD, k);
+
+ JavaValue result(T_VOID);
+ JavaCalls::call_static(&result, ik, vmSymbols::stopRemoteAgent_name(), vmSymbols::void_method_signature(), CHECK);
+}
+
diff --git a/src/share/vm/services/diagnosticCommand.hpp b/src/share/vm/services/diagnosticCommand.hpp
index c226a4ad6..d5c5cd172 100644
--- a/src/share/vm/services/diagnosticCommand.hpp
+++ b/src/share/vm/services/diagnosticCommand.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -214,4 +214,82 @@ public:
virtual void execute(TRAPS);
};
+// Enhanced JMX Agent support
+
+class JMXStartRemoteDCmd : public DCmdWithParser {
+
+ // Explicitly list all properties that could be
+ // passed to Agent.startRemoteManagementAgent()
+ // com.sun.management is omitted
+
+ DCmdArgument<char *> _config_file;
+ DCmdArgument<char *> _jmxremote_port;
+ DCmdArgument<char *> _jmxremote_rmi_port;
+ DCmdArgument<char *> _jmxremote_ssl;
+ DCmdArgument<char *> _jmxremote_registry_ssl;
+ DCmdArgument<char *> _jmxremote_authenticate;
+ DCmdArgument<char *> _jmxremote_password_file;
+ DCmdArgument<char *> _jmxremote_access_file;
+ DCmdArgument<char *> _jmxremote_login_config;
+ DCmdArgument<char *> _jmxremote_ssl_enabled_cipher_suites;
+ DCmdArgument<char *> _jmxremote_ssl_enabled_protocols;
+ DCmdArgument<char *> _jmxremote_ssl_need_client_auth;
+ DCmdArgument<char *> _jmxremote_ssl_config_file;
+
+public:
+ JMXStartRemoteDCmd(outputStream *output, bool heap_allocated);
+
+ static const char *name() {
+ return "ManagementAgent.start";
+ }
+
+ static const char *description() {
+ return "Start remote management agent.";
+ }
+
+ static int num_arguments();
+
+ virtual void execute(TRAPS);
+
+};
+
+class JMXStartLocalDCmd : public DCmd {
+
+ // Explicitly request start of local agent,
+ // it will not be started by start dcmd
+
+
+public:
+ JMXStartLocalDCmd(outputStream *output, bool heap_allocated);
+
+ static const char *name() {
+ return "ManagementAgent.start_local";
+ }
+
+ static const char *description() {
+ return "Start local management agent.";
+ }
+
+ virtual void execute(TRAPS);
+
+};
+
+class JMXStopRemoteDCmd : public DCmd {
+public:
+ JMXStopRemoteDCmd(outputStream *output, bool heap_allocated) :
+ DCmd(output, heap_allocated) {
+ // Do Nothing
+ }
+
+ static const char *name() {
+ return "ManagementAgent.stop";
+ }
+
+ static const char *description() {
+ return "Stop remote management agent.";
+ }
+
+ virtual void execute(TRAPS);
+};
+
#endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP