# HG changeset patch # User dholmes # Date 1327537595 18000 # Node ID d851f37146418f6a2589e34385e9d9af32f81cba # Parent 1ac084126285c7b8ebbd56dc17cc9f4056811bf8# Parent 5f3fcd591768d35e6489b28490cea5c3b0ab9802 Merge diff -r 1ac084126285 -r d851f3714641 .hgtags --- a/.hgtags Tue Jan 24 18:00:54 2012 -0500 +++ b/.hgtags Wed Jan 25 19:26:35 2012 -0500 @@ -207,3 +207,9 @@ a2fef924d8e6f37dac2a887315e3502876cc8e24 hs23-b08 61165f53f1656b9f99e4fb806429bf98b99d59c3 jdk8-b18 4bcf61041217f8677dcec18e90e9196acc945bba hs23-b09 +9232e0ecbc2cec54dcc8f93004fb00c214446460 jdk8-b19 +fe2c8764998112b7fefcd7d41599714813ae4327 jdk8-b20 +9952d1c439d64c5fd4ad1236a63a62bd5a49d4c3 jdk8-b21 +513351373923f74a7c91755748b95c9771e59f96 hs23-b10 +24727fb37561779077fdfa5a33342246f20e5c0f jdk8-b22 +dcc292399a39113957eebbd3e487b7e05e2c79fc hs23-b11 diff -r 1ac084126285 -r d851f3714641 make/Makefile --- a/make/Makefile Tue Jan 24 18:00:54 2012 -0500 +++ b/make/Makefile Wed Jan 25 19:26:35 2012 -0500 @@ -367,7 +367,7 @@ $(EXPORT_LIB_DIR)/%.jar: $(GEN_DIR)/%.jar $(install-file) -# Include files (jvmti.h, jvmticmlr.h, jni.h, $(JDK_INCLUDE_SUBDIR)/jni_md.h, jmm.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/% $(install-file) @@ -384,6 +384,16 @@ $(EXPORT_INCLUDE_DIR)/%: $(HS_SRC_DIR)/share/vm/services/% $(install-file) +JFR_EXISTS=$(shell if [ -d $(HS_ALT_SRC) ]; then echo 1; else echo 0; fi) +# export jfr.h +ifeq ($JFR_EXISTS,1) +$(EXPORT_INCLUDE_DIR)/%: $(HS_ALT_SRC)/share/vm/jfr/agent/% + $(install-file) +else +$(EXPORT_INCLUDE_DIR)/jfr.h: + +endif + # Doc files (jvmti.html) $(EXPORT_DOCS_DIR)/platform/jvmti/%: $(DOCS_DIR)/% $(install-file) diff -r 1ac084126285 -r d851f3714641 make/bsd/makefiles/vm.make --- a/make/bsd/makefiles/vm.make Tue Jan 24 18:00:54 2012 -0500 +++ b/make/bsd/makefiles/vm.make Wed Jan 25 19:26:35 2012 -0500 @@ -96,6 +96,10 @@ CPPFLAGS += -DDEFAULT_LIBPATH="\"$(DEFAULT_LIBPATH)\"" endif +ifndef JAVASE_EMBEDDED +CFLAGS += -DINCLUDE_TRACE +endif + # CFLAGS_WARN holds compiler options to suppress/enable warnings. CFLAGS += $(CFLAGS_WARN/BYFILE) @@ -147,6 +151,12 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +ifndef JAVASE_EMBEDDED +SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ + find $(HS_ALT_SRC)/share/vm/jfr -type d; \ + fi) +endif + CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) CORE_PATHS+=$(GENERATED)/jvmtifiles diff -r 1ac084126285 -r d851f3714641 make/defs.make --- a/make/defs.make Tue Jan 24 18:00:54 2012 -0500 +++ b/make/defs.make Wed Jan 25 19:26:35 2012 -0500 @@ -294,3 +294,7 @@ EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jni.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/$(JDK_INCLUDE_SUBDIR)/jni_md.h EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jmm.h + +ifndef JAVASE_EMBEDDED +EXPORT_LIST += $(EXPORT_INCLUDE_DIR)/jfr.h +endif diff -r 1ac084126285 -r d851f3714641 make/hotspot_version --- a/make/hotspot_version Tue Jan 24 18:00:54 2012 -0500 +++ b/make/hotspot_version Wed Jan 25 19:26:35 2012 -0500 @@ -35,7 +35,7 @@ HS_MAJOR_VER=23 HS_MINOR_VER=0 -HS_BUILD_NUMBER=10 +HS_BUILD_NUMBER=12 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 1ac084126285 -r d851f3714641 make/linux/makefiles/vm.make --- a/make/linux/makefiles/vm.make Tue Jan 24 18:00:54 2012 -0500 +++ b/make/linux/makefiles/vm.make Wed Jan 25 19:26:35 2012 -0500 @@ -98,6 +98,10 @@ ${JRE_VERSION} \ ${VM_DISTRO} +ifndef JAVASE_EMBEDDED +CFLAGS += -DINCLUDE_TRACE +endif + # CFLAGS_WARN holds compiler options to suppress/enable warnings. CFLAGS += $(CFLAGS_WARN/BYFILE) @@ -143,6 +147,12 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +ifndef JAVASE_EMBEDDED +SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ + find $(HS_ALT_SRC)/share/vm/jfr -type d; \ + fi) +endif + CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) CORE_PATHS+=$(GENERATED)/jvmtifiles diff -r 1ac084126285 -r d851f3714641 make/solaris/makefiles/vm.make --- a/make/solaris/makefiles/vm.make Tue Jan 24 18:00:54 2012 -0500 +++ b/make/solaris/makefiles/vm.make Wed Jan 25 19:26:35 2012 -0500 @@ -93,7 +93,7 @@ CFLAGS += $(CFLAGS/NOEX) # Extra flags from gnumake's invocation or environment -CFLAGS += $(EXTRA_CFLAGS) +CFLAGS += $(EXTRA_CFLAGS) -DINCLUDE_TRACE # Math Library (libm.so), do not use -lm. # There might be two versions of libm.so on the build system: @@ -160,6 +160,10 @@ SOURCE_PATHS+=$(HS_COMMON_SRC)/cpu/$(Platform_arch)/vm SOURCE_PATHS+=$(HS_COMMON_SRC)/os_cpu/$(Platform_os_arch)/vm +SOURCE_PATHS+=$(shell if [ -d $(HS_ALT_SRC)/share/vm/jfr ]; then \ + find $(HS_ALT_SRC)/share/vm/jfr -type d; \ + fi) + CORE_PATHS=$(foreach path,$(SOURCE_PATHS),$(call altsrc,$(path)) $(path)) CORE_PATHS+=$(GENERATED)/jvmtifiles diff -r 1ac084126285 -r d851f3714641 make/windows/build.bat --- a/make/windows/build.bat Tue Jan 24 18:00:54 2012 -0500 +++ b/make/windows/build.bat Wed Jan 25 19:26:35 2012 -0500 @@ -35,6 +35,8 @@ if %errorlevel% == 0 goto isia64 cl 2>&1 | grep "AMD64" >NUL if %errorlevel% == 0 goto amd64 +cl 2>&1 | grep "x64" >NUL +if %errorlevel% == 0 goto amd64 set ARCH=x86 set BUILDARCH=i486 set Platform_arch=x86 diff -r 1ac084126285 -r d851f3714641 make/windows/create_obj_files.sh --- a/make/windows/create_obj_files.sh Tue Jan 24 18:00:54 2012 -0500 +++ b/make/windows/create_obj_files.sh Wed Jan 25 19:26:35 2012 -0500 @@ -73,6 +73,13 @@ BASE_PATHS="${BASE_PATHS} ${GENERATED}/jvmtifiles" +if [ -d "${ALTSRC}/share/vm/jfr" ]; then + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/agent/isolated_deps/util" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr/jvm" + BASE_PATHS="${BASE_PATHS} ${ALTSRC}/share/vm/jfr" +fi + CORE_PATHS="${BASE_PATHS}" # shared is already in BASE_PATHS. Should add vm/memory but that one is also in BASE_PATHS. if [ -d "${ALTSRC}/share/vm/gc_implementation" ]; then diff -r 1ac084126285 -r d851f3714641 make/windows/makefiles/projectcreator.make --- a/make/windows/makefiles/projectcreator.make Tue Jan 24 18:00:54 2012 -0500 +++ b/make/windows/makefiles/projectcreator.make Wed Jan 25 19:26:35 2012 -0500 @@ -58,7 +58,8 @@ -absoluteInclude $(HOTSPOTBUILDSPACE)/%f/generated \ -ignorePath $(HOTSPOTBUILDSPACE)/%f/generated \ -ignorePath src\share\vm\adlc \ - -ignorePath src\share\vm\shark + -ignorePath src\share\vm\shark \ + -ignorePath posix # This is referenced externally by both the IDE and batch builds ProjectCreatorOptions= @@ -88,7 +89,7 @@ -jdkTargetRoot $(HOTSPOTJDKDIST) \ -define ALIGN_STACK_FRAMES \ -define VM_LITTLE_ENDIAN \ - -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \ + -prelink "" "Generating vm.def..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) set JAVA_HOME=$(HOTSPOTJDKDIST) $(HOTSPOTMKSHOME)\sh $(HOTSPOTWORKSPACE)\make\windows\build_vm_def.sh $(LINK_VER)" \ -postbuild "" "Building hotspot.exe..." "cd $(HOTSPOTBUILDSPACE)\%f\%b set HOTSPOTMKSHOME=$(HOTSPOTMKSHOME) nmake -f $(HOTSPOTWORKSPACE)\make\windows\projectfiles\common\Makefile LOCAL_MAKE=$(HOTSPOTBUILDSPACE)\%f\local.make JAVA_HOME=$(HOTSPOTJDKDIST) launcher" \ -ignoreFile jsig.c \ -ignoreFile jvmtiEnvRecommended.cpp \ diff -r 1ac084126285 -r d851f3714641 make/windows/makefiles/vm.make --- a/make/windows/makefiles/vm.make Tue Jan 24 18:00:54 2012 -0500 +++ b/make/windows/makefiles/vm.make Wed Jan 25 19:26:35 2012 -0500 @@ -19,7 +19,7 @@ # 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. -# +# # # Resource file containing VERSIONINFO @@ -30,7 +30,7 @@ COMMONSRC=$(WorkSpace)\src ALTSRC=$(WorkSpace)\src\closed -!ifdef RELEASE +!ifdef RELEASE !ifdef DEVELOP CPP_FLAGS=$(CPP_FLAGS) /D "DEBUG" !else @@ -74,6 +74,10 @@ CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_BUILD_USER=\"$(BuildUser)\"" CPP_FLAGS=$(CPP_FLAGS) /D "HOTSPOT_VM_DISTRO=\"$(HOTSPOT_VM_DISTRO)\"" +!ifndef JAVASE_EMBEDDED +CPP_FLAGS=$(CPP_FLAGS) /D "INCLUDE_TRACE" +!endif + CPP_FLAGS=$(CPP_FLAGS) $(CPP_INCLUDE_DIRS) # Define that so jni.h is on correct side @@ -97,7 +101,7 @@ !endif # If you modify exports below please do the corresponding changes in -# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java +# src/share/tools/ProjectCreator/WinGammaPlatformVC7.java LINK_FLAGS=$(LINK_FLAGS) $(STACK_SIZE) /subsystem:windows /dll /base:0x8000000 \ /export:JNI_GetDefaultJavaVMInitArgs \ /export:JNI_CreateJavaVM \ @@ -170,6 +174,7 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/prims VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/runtime VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/services +VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/trace VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/utilities VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/libadt VM_PATH=$(VM_PATH);$(WorkSpace)/src/os/windows/vm @@ -177,6 +182,13 @@ VM_PATH=$(VM_PATH);$(WorkSpace)/src/cpu/$(Platform_arch)/vm VM_PATH=$(VM_PATH);$(WorkSpace)/src/share/vm/opto +!if exists($(ALTSRC)\share\vm\jfr) +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/agent/isolated_deps/util +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr/jvm +VM_PATH=$(VM_PATH);$(ALTSRC)/share/vm/jfr +!endif + VM_PATH={$(VM_PATH)} # Special case files not using precompiled header files. @@ -263,6 +275,9 @@ {$(COMMONSRC)\share\vm\services}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< +{$(COMMONSRC)\share\vm\trace}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + {$(COMMONSRC)\share\vm\utilities}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< @@ -340,6 +355,9 @@ {$(ALTSRC)\share\vm\services}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< +{$(ALTSRC)\share\vm\trace}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + {$(ALTSRC)\share\vm\utilities}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< @@ -371,6 +389,18 @@ {..\generated\jvmtifiles}.cpp.obj:: $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< +{$(ALTSRC)\share\vm\jfr}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + +{$(ALTSRC)\share\vm\jfr\agent}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + +{$(ALTSRC)\share\vm\jfr\agent\isolated_deps\util}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + +{$(ALTSRC)\share\vm\jfr\jvm}.cpp.obj:: + $(CPP) $(CPP_FLAGS) $(CPP_USE_PCH) /c $< + default:: _build_pch_file.obj: diff -r 1ac084126285 -r d851f3714641 src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -391,7 +391,7 @@ __ call(Runtime1::entry_for(Runtime1::handle_exception_from_callee_id), relocInfo::runtime_call_type); __ delayed()->nop(); __ should_not_reach_here(); - assert(code_offset() - offset <= exception_handler_size, "overflow"); + guarantee(code_offset() - offset <= exception_handler_size, "overflow"); __ end_a_stub(); return offset; @@ -474,8 +474,7 @@ AddressLiteral deopt_blob(SharedRuntime::deopt_blob()->unpack()); __ JUMP(deopt_blob, G3_scratch, 0); // sethi;jmp __ delayed()->nop(); - assert(code_offset() - offset <= deopt_handler_size, "overflow"); - debug_only(__ stop("should have gone to the caller");) + guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); __ end_a_stub(); return offset; diff -r 1ac084126285 -r d851f3714641 src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp --- a/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/cpu/sparc/vm/c1_LIRAssembler_sparc.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -69,7 +69,7 @@ #else call_stub_size = 20, #endif // _LP64 - exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4), - deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(10*4) }; + exception_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(128), + deopt_handler_size = DEBUG_ONLY(1*K) NOT_DEBUG(64) }; #endif // CPU_SPARC_VM_C1_LIRASSEMBLER_SPARC_HPP diff -r 1ac084126285 -r d851f3714641 src/cpu/sparc/vm/frame_sparc.inline.hpp --- a/src/cpu/sparc/vm/frame_sparc.inline.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/cpu/sparc/vm/frame_sparc.inline.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -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 @@ -82,6 +82,8 @@ inline intptr_t* frame::sender_sp() const { return fp(); } +inline intptr_t* frame::real_fp() const { return fp(); } + // Used only in frame::oopmapreg_to_location // This return a value in VMRegImpl::slot_size inline int frame::pd_oop_map_offset_adjustment() const { diff -r 1ac084126285 -r d851f3714641 src/cpu/sparc/vm/methodHandles_sparc.cpp --- a/src/cpu/sparc/vm/methodHandles_sparc.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/cpu/sparc/vm/methodHandles_sparc.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1045,7 +1045,7 @@ |(1<unpack())); - - assert(code_offset() - offset <= deopt_handler_size, "overflow"); + guarantee(code_offset() - offset <= deopt_handler_size, "overflow"); __ end_a_stub(); return offset; diff -r 1ac084126285 -r d851f3714641 src/cpu/x86/vm/frame_x86.cpp --- a/src/cpu/x86/vm/frame_x86.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/cpu/x86/vm/frame_x86.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -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 @@ -675,3 +675,21 @@ // used to reset the saved FP return fp(); } + +intptr_t* frame::real_fp() const { + if (_cb != NULL) { + // use the frame size if valid + int size = _cb->frame_size(); + if ((size > 0) && + (! is_ricochet_frame())) { + // Work-around: ricochet explicitly excluded because frame size is not + // constant for the ricochet blob but its frame_size could not, for + // some reasons, be declared as <= 0. This potentially confusing + // size declaration should be fixed as another CR. + return unextended_sp() + size; + } + } + // else rely on fp() + assert(! is_compiled_frame(), "unknown compiled frame size"); + return fp(); +} diff -r 1ac084126285 -r d851f3714641 src/cpu/x86/vm/frame_x86.hpp --- a/src/cpu/x86/vm/frame_x86.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/cpu/x86/vm/frame_x86.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -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 @@ -188,6 +188,7 @@ frame(intptr_t* sp, intptr_t* fp); // accessors for the instance variables + // Note: not necessarily the real 'frame pointer' (see real_fp) intptr_t* fp() const { return _fp; } inline address* sender_pc_addr() const; diff -r 1ac084126285 -r d851f3714641 src/cpu/x86/vm/methodHandles_x86.cpp --- a/src/cpu/x86/vm/methodHandles_x86.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/cpu/x86/vm/methodHandles_x86.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1005,7 +1005,7 @@ intptr_t* base_sp = last_sp; typedef MethodHandles::RicochetFrame RicochetFrame; RicochetFrame* rfp = (RicochetFrame*)((address)saved_bp - RicochetFrame::sender_link_offset_in_bytes()); - if (!UseRicochetFrames || Universe::heap()->is_in((address) rfp->saved_args_base())) { + if (Universe::heap()->is_in((address) rfp->saved_args_base())) { // Probably an interpreter frame. base_sp = (intptr_t*) saved_bp[frame::interpreter_frame_monitor_block_top_offset]; } @@ -1104,7 +1104,7 @@ |(1< - -#ifdef __APPLE__ - -void Decoder::initialize() { - _initialized = true; -} - -void Decoder::uninitialize() { - _initialized = false; -} - -bool Decoder::can_decode_C_frame_in_vm() { - return false; -} - -Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) { - return symbol_not_found; -} - - -#endif - -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { - int status; - char* result; - size_t size = (size_t)buflen; - - // Don't pass buf to __cxa_demangle. In case of the 'buf' is too small, - // __cxa_demangle will call system "realloc" for additional memory, which - // may use different malloc/realloc mechanism that allocates 'buf'. - if ((result = abi::__cxa_demangle(symbol, NULL, NULL, &status)) != NULL) { - jio_snprintf(buf, buflen, "%s", result); - // call c library's free - ::free(result); - return true; - } - return false; -} diff -r 1ac084126285 -r d851f3714641 src/os/bsd/vm/decoder_machO.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/decoder_machO.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#ifdef __APPLE__ +#include "decoder_machO.hpp" +#endif + + diff -r 1ac084126285 -r d851f3714641 src/os/bsd/vm/decoder_machO.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/bsd/vm/decoder_machO.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_BSD_VM_DECODER_MACHO_HPP +#define OS_BSD_VM_DECODER_MACHO_HPP + +#ifdef __APPLE__ + +#include "utilities/decoder.hpp" + +// Just a placehold for now +class MachODecoder: public NullDecoder { +public: + MachODecoder() { } + ~MachODecoder() { } +}; + +#endif + +#endif // OS_BSD_VM_DECODER_MACHO_HPP + diff -r 1ac084126285 -r d851f3714641 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/os/bsd/vm/os_bsd.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1920,7 +1920,7 @@ return true; } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } diff -r 1ac084126285 -r d851f3714641 src/os/linux/vm/decoder_linux.cpp --- a/src/os/linux/vm/decoder_linux.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/os/linux/vm/decoder_linux.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -23,11 +23,11 @@ */ #include "prims/jvm.h" -#include "utilities/decoder.hpp" +#include "utilities/decoder_elf.hpp" #include -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { +bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) { int status; char* result; size_t size = (size_t)buflen; @@ -43,3 +43,4 @@ } return false; } + diff -r 1ac084126285 -r d851f3714641 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/os/linux/vm/os_linux.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1732,7 +1732,7 @@ return true; } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } diff -r 1ac084126285 -r d851f3714641 src/os/solaris/vm/decoder_solaris.cpp --- a/src/os/solaris/vm/decoder_solaris.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/os/solaris/vm/decoder_solaris.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -22,10 +22,11 @@ * */ -#include "utilities/decoder.hpp" +#include "utilities/decoder_elf.hpp" #include -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { +bool ElfDecoder::demangle(const char* symbol, char *buf, int buflen) { return !cplus_demangle(symbol, buf, (size_t)buflen); } + diff -r 1ac084126285 -r d851f3714641 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/os/solaris/vm/os_solaris.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1997,7 +1997,7 @@ } if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } @@ -2015,7 +2015,7 @@ return true; } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - dlinfo.dli_fname, buf, buflen, offset) == Decoder::no_error) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } diff -r 1ac084126285 -r d851f3714641 src/os/windows/vm/decoder_windows.cpp --- a/src/os/windows/vm/decoder_windows.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/os/windows/vm/decoder_windows.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -24,22 +24,24 @@ #include "precompiled.hpp" #include "prims/jvm.h" -#include "runtime/os.hpp" -#include "utilities/decoder.hpp" +#include "decoder_windows.hpp" + +WindowsDecoder::WindowsDecoder() { + _dbghelp_handle = NULL; + _can_decode_in_vm = false; + _pfnSymGetSymFromAddr64 = NULL; + _pfnUndecorateSymbolName = NULL; -HMODULE Decoder::_dbghelp_handle = NULL; -bool Decoder::_can_decode_in_vm = false; -pfn_SymGetSymFromAddr64 Decoder::_pfnSymGetSymFromAddr64 = NULL; -pfn_UndecorateSymbolName Decoder::_pfnUndecorateSymbolName = NULL; + _decoder_status = no_error; + initialize(); +} -void Decoder::initialize() { - if (!_initialized) { - _initialized = true; - - HINSTANCE handle = os::win32::load_Windows_dll("dbghelp.dll", NULL, 0); +void WindowsDecoder::initialize() { + if (!has_error() && _dbghelp_handle == NULL) { + HMODULE handle = ::LoadLibrary("dbghelp.dll"); if (!handle) { _decoder_status = helper_not_found; - return; + return; } _dbghelp_handle = handle; @@ -70,32 +72,29 @@ // find out if jvm.dll contains private symbols, by decoding // current function and comparing the result - address addr = (address)Decoder::initialize; + address addr = (address)Decoder::decode; char buf[MAX_PATH]; - if (decode(addr, buf, sizeof(buf), NULL) == no_error) { - _can_decode_in_vm = !strcmp(buf, "Decoder::initialize"); + if (decode(addr, buf, sizeof(buf), NULL)) { + _can_decode_in_vm = !strcmp(buf, "Decoder::decode"); } } } -void Decoder::uninitialize() { - assert(_initialized, "Decoder not yet initialized"); +void WindowsDecoder::uninitialize() { _pfnSymGetSymFromAddr64 = NULL; _pfnUndecorateSymbolName = NULL; if (_dbghelp_handle != NULL) { ::FreeLibrary(_dbghelp_handle); } - _initialized = false; + _dbghelp_handle = NULL; } -bool Decoder::can_decode_C_frame_in_vm() { - initialize(); - return _can_decode_in_vm; +bool WindowsDecoder::can_decode_C_frame_in_vm() const { + return (!has_error() && _can_decode_in_vm); } -Decoder::decoder_status Decoder::decode(address addr, char *buf, int buflen, int *offset) { - assert(_initialized, "Decoder not yet initialized"); +bool WindowsDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* modulepath) { if (_pfnSymGetSymFromAddr64 != NULL) { PIMAGEHLP_SYMBOL64 pSymbol; char symbolInfo[MAX_PATH + sizeof(IMAGEHLP_SYMBOL64)]; @@ -105,19 +104,20 @@ DWORD64 displacement; if (_pfnSymGetSymFromAddr64(::GetCurrentProcess(), (DWORD64)addr, &displacement, pSymbol)) { if (buf != NULL) { - if (!demangle(pSymbol->Name, buf, buflen)) { + if (demangle(pSymbol->Name, buf, buflen)) { jio_snprintf(buf, buflen, "%s", pSymbol->Name); } } - if (offset != NULL) *offset = (int)displacement; - return no_error; + if(offset != NULL) *offset = (int)displacement; + return true; } } - return helper_not_found; + if (buf != NULL && buflen > 0) buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; } -bool Decoder::demangle(const char* symbol, char *buf, int buflen) { - assert(_initialized, "Decoder not yet initialized"); +bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) { return _pfnUndecorateSymbolName != NULL && _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE); } diff -r 1ac084126285 -r d851f3714641 src/os/windows/vm/decoder_windows.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/windows/vm/decoder_windows.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef OS_WINDOWS_VM_DECODER_WINDOWS_HPP +#define OS_WINDOWS_VM_DECIDER_WINDOWS_HPP + +#include +#include + +#include "utilities/decoder.hpp" + +// functions needed for decoding symbols +typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD); +typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL); +typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); +typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); + +class WindowsDecoder: public NullDecoder { + +public: + WindowsDecoder(); + ~WindowsDecoder() { uninitialize(); }; + + bool can_decode_C_frame_in_vm() const; + bool demangle(const char* symbol, char *buf, int buflen); + bool decode(address addr, char *buf, int buflen, int* offset, const char* modulepath = NULL); + +private: + void initialize(); + void uninitialize(); + +private: + HMODULE _dbghelp_handle; + bool _can_decode_in_vm; + pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64; + pfn_UndecorateSymbolName _pfnUndecorateSymbolName; +}; + +#endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP + diff -r 1ac084126285 -r d851f3714641 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/os/windows/vm/os_windows.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1391,7 +1391,7 @@ bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset) { - if (Decoder::decode(addr, buf, buflen, offset) == Decoder::no_error) { + if (Decoder::decode(addr, buf, buflen, offset)) { return true; } if (offset != NULL) *offset = -1; diff -r 1ac084126285 -r d851f3714641 src/share/vm/classfile/symbolTable.cpp --- a/src/share/vm/classfile/symbolTable.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/classfile/symbolTable.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -204,6 +204,24 @@ return s; } +// Look up the address of the literal in the SymbolTable for this Symbol* +// Do not create any new symbols +// Do not increment the reference count to keep this alive +Symbol** SymbolTable::lookup_symbol_addr(Symbol* sym){ + unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length()); + int index = the_table()->hash_to_index(hash); + + for (HashtableEntry* e = the_table()->bucket(index); e != NULL; e = e->next()) { + if (e->hash() == hash) { + Symbol* literal_sym = e->literal(); + if (sym == literal_sym) { + return e->literal_addr(); + } + } + } + return NULL; +} + // Suggestion: Push unicode-based lookup all the way into the hashing // and probing logic, so there is no need for convert_to_utf8 until // an actual new Symbol* is created. diff -r 1ac084126285 -r d851f3714641 src/share/vm/classfile/symbolTable.hpp --- a/src/share/vm/classfile/symbolTable.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/classfile/symbolTable.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -144,6 +144,9 @@ static void release(Symbol* sym); + // Look up the address of the literal in the SymbolTable for this Symbol* + static Symbol** lookup_symbol_addr(Symbol* sym); + // jchar (utf16) version of lookups static Symbol* lookup_unicode(const jchar* name, int len, TRAPS); static Symbol* lookup_only_unicode(const jchar* name, int len, unsigned int& hash); diff -r 1ac084126285 -r d851f3714641 src/share/vm/classfile/systemDictionary.cpp --- a/src/share/vm/classfile/systemDictionary.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/classfile/systemDictionary.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -2131,6 +2131,12 @@ } } + // Assign a classid if one has not already been assigned. The + // counter does not need to be atomically incremented since this + // is only done while holding the SystemDictionary_lock. + // All loaded classes get a unique ID. + TRACE_INIT_ID(k); + // Check for a placeholder. If there, remove it and make a // new system dictionary entry. placeholders()->find_and_remove(p_index, p_hash, name, class_loader, THREAD); diff -r 1ac084126285 -r d851f3714641 src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/oops/klass.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -158,6 +158,9 @@ kl->set_next_sibling(NULL); kl->set_alloc_count(0); kl->set_alloc_size(0); +#ifdef TRACE_SET_KLASS_TRACE_ID + TRACE_SET_KLASS_TRACE_ID(kl, 0); +#endif kl->set_prototype_header(markOopDesc::prototype()); kl->set_biased_lock_revocation_count(0); diff -r 1ac084126285 -r d851f3714641 src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/oops/klass.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -33,6 +33,7 @@ #include "oops/klassPS.hpp" #include "oops/oop.hpp" #include "runtime/orderAccess.hpp" +#include "trace/traceMacros.hpp" #include "utilities/accessFlags.hpp" #ifndef SERIALGC #include "gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp" @@ -80,6 +81,7 @@ // [last_biased_lock_bulk_revocation_time] (64 bits) // [prototype_header] // [biased_lock_revocation_count] +// [trace_id] // Forward declarations. @@ -263,6 +265,9 @@ markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; +#ifdef TRACE_DEFINE_KLASS_TRACE_ID + TRACE_DEFINE_KLASS_TRACE_ID; +#endif public: // returns the enclosing klassOop @@ -683,6 +688,9 @@ jlong last_biased_lock_bulk_revocation_time() { return _last_biased_lock_bulk_revocation_time; } void set_last_biased_lock_bulk_revocation_time(jlong cur_time) { _last_biased_lock_bulk_revocation_time = cur_time; } +#ifdef TRACE_DEFINE_KLASS_METHODS + TRACE_DEFINE_KLASS_METHODS; +#endif // garbage collection support virtual void follow_weak_klass_links( diff -r 1ac084126285 -r d851f3714641 src/share/vm/oops/methodKlass.cpp --- a/src/share/vm/oops/methodKlass.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/oops/methodKlass.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -83,6 +83,7 @@ m->set_max_stack(0); m->set_max_locals(0); m->set_intrinsic_id(vmIntrinsics::_none); + m->set_jfr_towrite(false); m->set_method_data(NULL); m->set_interpreter_throwout_count(0); m->set_vtable_index(methodOopDesc::garbage_vtable_index); diff -r 1ac084126285 -r d851f3714641 src/share/vm/oops/methodOop.hpp --- a/src/share/vm/oops/methodOop.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/oops/methodOop.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -77,7 +77,7 @@ // | method_size | max_stack | // | max_locals | size_of_parameters | // |------------------------------------------------------| -// | intrinsic_id, (unused) | throwout_count | +// |intrinsic_id| flags | throwout_count | // |------------------------------------------------------| // | num_breakpoints | (unused) | // |------------------------------------------------------| @@ -124,6 +124,8 @@ u2 _max_locals; // Number of local variables used by this method u2 _size_of_parameters; // size of the parameter block (receiver + arguments) in words u1 _intrinsic_id; // vmSymbols::intrinsic_id (0 == _none) + u1 _jfr_towrite : 1, // Flags + : 7; u2 _interpreter_throwout_count; // Count of times method was exited via exception while interpreting u2 _number_of_breakpoints; // fullspeed debugging support InvocationCounter _invocation_counter; // Incremented before each activation of the method - used to trigger frequency-based optimizations @@ -225,6 +227,7 @@ void clear_number_of_breakpoints() { _number_of_breakpoints = 0; } // index into instanceKlass methods() array + // note: also used by jfr u2 method_idnum() const { return constMethod()->method_idnum(); } void set_method_idnum(u2 idnum) { constMethod()->set_method_idnum(idnum); } @@ -650,6 +653,9 @@ void init_intrinsic_id(); // updates from _none if a match static vmSymbols::SID klass_id_for_intrinsics(klassOop holder); + bool jfr_towrite() { return _jfr_towrite; } + void set_jfr_towrite(bool towrite) { _jfr_towrite = towrite; } + // On-stack replacement support bool has_osr_nmethod(int level, bool match_level) { return instanceKlass::cast(method_holder())->lookup_osr_nmethod(this, InvocationEntryBci, level, match_level) != NULL; diff -r 1ac084126285 -r d851f3714641 src/share/vm/opto/callnode.cpp --- a/src/share/vm/opto/callnode.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/opto/callnode.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1625,21 +1625,20 @@ //============================================================================= bool LockNode::is_nested_lock_region() { - Node* box = box_node(); - if (!box->is_BoxLock() || box->as_BoxLock()->stack_slot() <= 0) + BoxLockNode* box = box_node()->as_BoxLock(); + int stk_slot = box->stack_slot(); + if (stk_slot <= 0) return false; // External lock or it is not Box (Phi node). // Ignore complex cases: merged locks or multiple locks. - BoxLockNode* box_lock = box->as_BoxLock(); Node* obj = obj_node(); LockNode* unique_lock = NULL; - if (!box_lock->is_simple_lock_region(&unique_lock, obj) || + if (!box->is_simple_lock_region(&unique_lock, obj) || (unique_lock != this)) { return false; } // Look for external lock for the same object. - int stk_slot = box_lock->stack_slot(); SafePointNode* sfn = this->as_SafePoint(); JVMState* youngest_jvms = sfn->jvms(); int max_depth = youngest_jvms->depth(); @@ -1649,7 +1648,7 @@ // Loop over monitors for (int idx = 0; idx < num_mon; idx++) { Node* obj_node = sfn->monitor_obj(jvms, idx); - BoxLockNode* box_node = BoxLockNode::box_node(sfn->monitor_box(jvms, idx)); + BoxLockNode* box_node = sfn->monitor_box(jvms, idx)->as_BoxLock(); if ((box_node->stack_slot() < stk_slot) && obj_node->eqv_uncast(obj)) { return true; } diff -r 1ac084126285 -r d851f3714641 src/share/vm/opto/locknode.cpp --- a/src/share/vm/opto/locknode.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/opto/locknode.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -63,7 +63,7 @@ } BoxLockNode* BoxLockNode::box_node(Node* box) { - // Chase down the BoxNode + // Chase down the BoxNode after RA which may spill box nodes. while (!box->is_BoxLock()) { // if (box_node->is_SpillCopy()) { // Node *m = box_node->in(1); @@ -84,18 +84,13 @@ return box_node(box)->in_RegMask(0).find_first_elem(); } -bool BoxLockNode::same_slot(Node* box1, Node* box2) { - return box_node(box1)->_slot == box_node(box2)->_slot; -} - // Is BoxLock node used for one simple lock region (same box and obj)? bool BoxLockNode::is_simple_lock_region(LockNode** unique_lock, Node* obj) { LockNode* lock = NULL; bool has_one_lock = false; for (uint i = 0; i < this->outcnt(); i++) { Node* n = this->raw_out(i); - if (n->is_Phi()) - return false; // Merged regions + assert(!n->is_Phi(), "should not merge BoxLock nodes"); if (n->is_AbstractLock()) { AbstractLockNode* alock = n->as_AbstractLock(); // Check lock's box since box could be referenced by Lock's debug info. @@ -123,23 +118,12 @@ FastLockNode* flock = n->as_FastLock(); assert((flock->box_node() == this) && flock->obj_node()->eqv_uncast(obj),""); } - if (n->is_SafePoint() && n->as_SafePoint()->jvms()) { - SafePointNode* sfn = n->as_SafePoint(); - JVMState* youngest_jvms = sfn->jvms(); - int max_depth = youngest_jvms->depth(); - for (int depth = 1; depth <= max_depth; depth++) { - JVMState* jvms = youngest_jvms->of_depth(depth); - int num_mon = jvms->nof_monitors(); - // Loop over monitors - for (int idx = 0; idx < num_mon; idx++) { - Node* obj_node = sfn->monitor_obj(jvms, idx); - Node* box_node = sfn->monitor_box(jvms, idx); - if (box_node == this) { - assert(obj_node->eqv_uncast(obj),""); - } - } - } - } + // Don't check monitor info in safepoints since the referenced object could + // be different from the locked object. It could be Phi node of different + // cast nodes which point to this locked object. + // We assume that no other objects could be referenced in monitor info + // associated with this BoxLock node because all associated locks and + // unlocks are reference only this one object. } #endif if (unique_lock != NULL && has_one_lock) { diff -r 1ac084126285 -r d851f3714641 src/share/vm/opto/locknode.hpp --- a/src/share/vm/opto/locknode.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/opto/locknode.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -49,9 +49,9 @@ //------------------------------BoxLockNode------------------------------------ class BoxLockNode : public Node { - const int _slot; - RegMask _inmask; - bool _is_eliminated; // indicates this lock was safely eliminated + const int _slot; // stack slot + RegMask _inmask; // OptoReg corresponding to stack slot + bool _is_eliminated; // Associated locks were safely eliminated public: BoxLockNode( int lock ); @@ -68,7 +68,9 @@ static OptoReg::Name reg(Node* box_node); static BoxLockNode* box_node(Node* box_node); - static bool same_slot(Node* box1, Node* box2); + static bool same_slot(Node* box1, Node* box2) { + return box1->as_BoxLock()->_slot == box2->as_BoxLock()->_slot; + } int stack_slot() const { return _slot; } bool is_eliminated() const { return _is_eliminated; } diff -r 1ac084126285 -r d851f3714641 src/share/vm/opto/macro.cpp --- a/src/share/vm/opto/macro.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/opto/macro.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1802,10 +1802,14 @@ // Mark all associated (same box and obj) lock and unlock nodes for // elimination if some of them marked already. void PhaseMacroExpand::mark_eliminated_box(Node* oldbox, Node* obj) { - if (oldbox->is_BoxLock() && oldbox->as_BoxLock()->is_eliminated()) - return; + if (oldbox->as_BoxLock()->is_eliminated()) + return; // This BoxLock node was processed already. - if (oldbox->is_BoxLock() && + // New implementation (EliminateNestedLocks) has separate BoxLock + // node for each locked region so mark all associated locks/unlocks as + // eliminated even if different objects are referenced in one locked region + // (for example, OSR compilation of nested loop inside locked scope). + if (EliminateNestedLocks || oldbox->as_BoxLock()->is_simple_lock_region(NULL, obj)) { // Box is used only in one lock region. Mark this box as eliminated. _igvn.hash_delete(oldbox); @@ -1818,7 +1822,6 @@ AbstractLockNode* alock = u->as_AbstractLock(); // Check lock's box since box could be referenced by Lock's debug info. if (alock->box_node() == oldbox) { - assert(alock->obj_node()->eqv_uncast(obj), ""); // Mark eliminated all related locks and unlocks. alock->set_non_esc_obj(); } @@ -1829,8 +1832,7 @@ // Create new "eliminated" BoxLock node and use it in monitor debug info // instead of oldbox for the same object. - BoxLockNode* box = BoxLockNode::box_node(oldbox); - BoxLockNode* newbox = box->clone()->as_BoxLock(); + BoxLockNode* newbox = oldbox->clone()->as_BoxLock(); // Note: BoxLock node is marked eliminated only here and it is used // to indicate that all associated lock and unlock nodes are marked @@ -2047,7 +2049,7 @@ Node* box = lock->box_node(); Node* flock = lock->fastlock_node(); - assert(!BoxLockNode::box_node(box)->is_eliminated(), "sanity"); + assert(!box->as_BoxLock()->is_eliminated(), "sanity"); // Make the merge point Node *region; @@ -2283,7 +2285,7 @@ Node* obj = unlock->obj_node(); Node* box = unlock->box_node(); - assert(!BoxLockNode::box_node(box)->is_eliminated(), "sanity"); + assert(!box->as_BoxLock()->is_eliminated(), "sanity"); // No need for a null check on unlock diff -r 1ac084126285 -r d851f3714641 src/share/vm/opto/parse1.cpp --- a/src/share/vm/opto/parse1.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/opto/parse1.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1604,7 +1604,16 @@ continue; default: // All normal stuff if (phi == NULL) { - if (!check_elide_phi || !target->can_elide_SEL_phi(j)) { + const JVMState* jvms = map()->jvms(); + if (EliminateNestedLocks && + jvms->is_mon(j) && jvms->is_monitor_box(j)) { + // BoxLock nodes are not commoning. + // Use old BoxLock node as merged box. + assert(newin->jvms()->is_monitor_box(j), "sanity"); + // This assert also tests that nodes are BoxLock. + assert(BoxLockNode::same_slot(n, m), "sanity"); + C->gvn_replace_by(n, m); + } else if (!check_elide_phi || !target->can_elide_SEL_phi(j)) { phi = ensure_phi(j, nophi); } } @@ -1819,12 +1828,8 @@ } else if (jvms->is_stk(idx)) { t = block()->stack_type_at(idx - jvms->stkoff()); } else if (jvms->is_mon(idx)) { - if (EliminateNestedLocks && jvms->is_monitor_box(idx)) { - // BoxLock nodes are not commoning. Create Phi. - t = o->bottom_type(); // TypeRawPtr::BOTTOM - } else { - t = TypeInstPtr::BOTTOM; // this is sufficient for a lock object - } + assert(!jvms->is_monitor_box(idx), "no phis for boxes"); + t = TypeInstPtr::BOTTOM; // this is sufficient for a lock object } else if ((uint)idx < TypeFunc::Parms) { t = o->bottom_type(); // Type::RETURN_ADDRESS or such-like. } else { diff -r 1ac084126285 -r d851f3714641 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/prims/jni.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -48,6 +48,7 @@ #include "oops/typeArrayOop.hpp" #include "prims/jni.h" #include "prims/jniCheck.hpp" +#include "prims/jniExport.hpp" #include "prims/jniFastGetField.hpp" #include "prims/jvm.h" #include "prims/jvm_misc.hpp" @@ -66,6 +67,8 @@ #include "runtime/signature.hpp" #include "runtime/vm_operations.hpp" #include "services/runtimeService.hpp" +#include "trace/tracing.hpp" +#include "trace/traceEventTypes.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -5139,6 +5142,11 @@ if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_start(thread); } + + EVENT_BEGIN(TraceEventThreadStart, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + // Check if we should compile all classes on bootclasspath NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();) // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving. @@ -5337,6 +5345,10 @@ JvmtiExport::post_thread_start(thread); } + EVENT_BEGIN(TraceEventThreadStart, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + *(JNIEnv**)penv = thread->jni_environment(); // Now leaving the VM, so change thread_state. This is normally automatically taken care @@ -5464,8 +5476,7 @@ return ret; } - if (JvmtiExport::is_jvmti_version(version)) { - ret = JvmtiExport::get_jvmti_interface(vm, penv, version); + if (JniExportedInterface::GetExportedInterface(vm, penv, version, &ret)) { return ret; } diff -r 1ac084126285 -r d851f3714641 src/share/vm/prims/jniExport.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/prims/jniExport.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,42 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_PRIMS_JNI_EXPORT_HPP +#define SHARE_VM_PRIMS_JNI_EXPORT_HPP + +#include "prims/jni.h" +#include "prims/jvmtiExport.hpp" + +class JniExportedInterface { + public: + static bool GetExportedInterface(JavaVM* vm, void** penv, jint version, jint* iface) { + if (JvmtiExport::is_jvmti_version(version)) { + *iface = JvmtiExport::get_jvmti_interface(vm, penv, version); + return true; + } + return false; + } +}; + +#endif // SHARE_VM_PRIMS_JNI_EXPORT_HPP diff -r 1ac084126285 -r d851f3714641 src/share/vm/prims/methodHandles.cpp --- a/src/share/vm/prims/methodHandles.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/prims/methodHandles.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -194,9 +194,6 @@ // MethodHandles::generate_adapters // void MethodHandles::generate_adapters() { -#ifdef TARGET_ARCH_NYI_6939861 - if (FLAG_IS_DEFAULT(UseRicochetFrames)) UseRicochetFrames = false; -#endif if (!EnableInvokeDynamic || SystemDictionary::MethodHandle_klass() == NULL) return; assert(_adapter_code == NULL, "generate only once"); @@ -230,18 +227,6 @@ } -#ifdef TARGET_ARCH_NYI_6939861 -// these defs belong in methodHandles_.cpp -frame MethodHandles::ricochet_frame_sender(const frame& fr, RegisterMap *map) { - ShouldNotCallThis(); - return fr; -} -void MethodHandles::ricochet_frame_oops_do(const frame& fr, OopClosure* f, const RegisterMap* reg_map) { - ShouldNotCallThis(); -} -#endif //TARGET_ARCH_NYI_6939861 - - //------------------------------------------------------------------------------ // MethodHandles::ek_supported // @@ -251,28 +236,11 @@ case _adapter_unused_13: return false; // not defined yet case _adapter_prim_to_ref: - return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF); + return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_PRIM_TO_REF); case _adapter_collect_args: - return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS); + return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_COLLECT_ARGS); case _adapter_fold_args: - return UseRicochetFrames && conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS); - case _adapter_opt_return_any: - return UseRicochetFrames; -#ifdef TARGET_ARCH_NYI_6939861 - // ports before 6939861 supported only three kinds of spread ops - case _adapter_spread_args: - // restrict spreads to three kinds: - switch (ek) { - case _adapter_opt_spread_0: - case _adapter_opt_spread_1: - case _adapter_opt_spread_more: - break; - default: - return false; - break; - } - break; -#endif //TARGET_ARCH_NYI_6939861 + return conv_op_supported(java_lang_invoke_AdapterMethodHandle::OP_FOLD_ARGS); } return true; } @@ -1988,9 +1956,6 @@ case _adapter_prim_to_ref: // boxer MH to use case _adapter_collect_args: // method handle which collects the args case _adapter_fold_args: // method handle which collects the args - if (!UseRicochetFrames) { - { err = "box/collect/fold operators are not supported"; break; } - } if (!java_lang_invoke_MethodHandle::is_instance(argument())) { err = "MethodHandle adapter argument required"; break; } arg_mtype = Handle(THREAD, java_lang_invoke_MethodHandle::type(argument())); @@ -2370,7 +2335,6 @@ case _adapter_prim_to_ref: { - assert(UseRicochetFrames, "else don't come here"); // vminfo will be the location to insert the return value vminfo = argslot; ek_opt = _adapter_opt_collect_ref; @@ -2436,20 +2400,6 @@ case _adapter_spread_args: { -#ifdef TARGET_ARCH_NYI_6939861 - // ports before 6939861 supported only three kinds of spread ops - if (!UseRicochetFrames) { - int array_size = slots_pushed + 1; - assert(array_size >= 0, ""); - vminfo = array_size; - switch (array_size) { - case 0: ek_opt = _adapter_opt_spread_0; break; - case 1: ek_opt = _adapter_opt_spread_1; break; - default: ek_opt = _adapter_opt_spread_more; break; - } - break; - } -#endif //TARGET_ARCH_NYI_6939861 // vminfo will be the required length of the array int array_size = (slots_pushed + 1) / (type2size[dest] == 2 ? 2 : 1); vminfo = array_size; @@ -2494,7 +2444,6 @@ case _adapter_collect_args: { - assert(UseRicochetFrames, "else don't come here"); int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); // vminfo will be the location to insert the return value vminfo = argslot; @@ -2563,7 +2512,6 @@ case _adapter_fold_args: { - assert(UseRicochetFrames, "else don't come here"); int elem_slots = argument_slot_count(java_lang_invoke_MethodHandle::type(argument())); // vminfo will be the location to insert the return value vminfo = argslot + elem_slots; diff -r 1ac084126285 -r d851f3714641 src/share/vm/prims/methodHandles.hpp --- a/src/share/vm/prims/methodHandles.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/prims/methodHandles.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -738,46 +738,6 @@ #ifdef TARGET_ARCH_ppc # include "methodHandles_ppc.hpp" #endif - -#ifdef TARGET_ARCH_NYI_6939861 - // Here are some backward compatible declarations until the 6939861 ports are updated. - #define _adapter_flyby (_EK_LIMIT + 10) - #define _adapter_ricochet (_EK_LIMIT + 11) - #define _adapter_opt_spread_1 _adapter_opt_spread_1_ref - #define _adapter_opt_spread_more _adapter_opt_spread_ref - enum { - _INSERT_NO_MASK = -1, - _INSERT_REF_MASK = 0, - _INSERT_INT_MASK = 1, - _INSERT_LONG_MASK = 3 - }; - static void get_ek_bound_mh_info(EntryKind ek, BasicType& arg_type, int& arg_mask, int& arg_slots) { - arg_type = ek_bound_mh_arg_type(ek); - arg_mask = 0; - arg_slots = type2size[arg_type];; - } - static void get_ek_adapter_opt_swap_rot_info(EntryKind ek, int& swap_bytes, int& rotate) { - int swap_slots = ek_adapter_opt_swap_slots(ek); - rotate = ek_adapter_opt_swap_mode(ek); - swap_bytes = swap_slots * Interpreter::stackElementSize; - } - static int get_ek_adapter_opt_spread_info(EntryKind ek) { - return ek_adapter_opt_spread_count(ek); - } - - static void insert_arg_slots(MacroAssembler* _masm, - RegisterOrConstant arg_slots, - int arg_mask, - Register argslot_reg, - Register temp_reg, Register temp2_reg, Register temp3_reg = noreg); - - static void remove_arg_slots(MacroAssembler* _masm, - RegisterOrConstant arg_slots, - Register argslot_reg, - Register temp_reg, Register temp2_reg, Register temp3_reg = noreg); - - static void trace_method_handle(MacroAssembler* _masm, const char* adaptername) PRODUCT_RETURN; -#endif //TARGET_ARCH_NYI_6939861 }; diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/frame.cpp --- a/src/share/vm/runtime/frame.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/frame.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -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 @@ -1334,24 +1334,21 @@ void frame::describe(FrameValues& values, int frame_no) { + intptr_t* frame_pointer = real_fp(); if (is_entry_frame() || is_compiled_frame() || is_interpreted_frame() || is_native_frame()) { // Label values common to most frames values.describe(-1, unextended_sp(), err_msg("unextended_sp for #%d", frame_no)); values.describe(-1, sp(), err_msg("sp for #%d", frame_no)); - if (is_compiled_frame()) { - values.describe(-1, sp() + _cb->frame_size(), err_msg("computed fp for #%d", frame_no)); - } else { - values.describe(-1, fp(), err_msg("fp for #%d", frame_no)); - } + values.describe(-1, frame_pointer, err_msg("frame pointer for #%d", frame_no)); } if (is_interpreted_frame()) { methodOop m = interpreter_frame_method(); int bci = interpreter_frame_bci(); // Label the method and current bci - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), FormatBuffer<1024>("#%d method %s @ %d", frame_no, m->name_and_sig_as_C_string(), bci), 2); - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), err_msg("- %d locals %d max stack", m->max_locals(), m->max_stack()), 1); if (m->max_locals() > 0) { intptr_t* l0 = interpreter_frame_local_at(0); @@ -1383,18 +1380,18 @@ } } else if (is_entry_frame()) { // For now just label the frame - values.describe(-1, MAX2(sp(), fp()), err_msg("#%d entry frame", frame_no), 2); + values.describe(-1, MAX2(sp(), frame_pointer), err_msg("#%d entry frame", frame_no), 2); } else if (is_compiled_frame()) { // For now just label the frame nmethod* nm = cb()->as_nmethod_or_null(); - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for method %s%s", frame_no, nm, nm->method()->name_and_sig_as_C_string(), is_deoptimized_frame() ? " (deoptimized" : ""), 2); } else if (is_native_frame()) { // For now just label the frame nmethod* nm = cb()->as_nmethod_or_null(); - values.describe(-1, MAX2(sp(), fp()), + values.describe(-1, MAX2(sp(), frame_pointer), FormatBuffer<1024>("#%d nmethod " INTPTR_FORMAT " for native method %s", frame_no, nm, nm->method()->name_and_sig_as_C_string()), 2); } diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/frame.hpp --- a/src/share/vm/runtime/frame.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/frame.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -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 @@ -221,6 +221,15 @@ // returns the stack pointer of the calling frame intptr_t* sender_sp() const; + // Returns the real 'frame pointer' for the current frame. + // This is the value expected by the platform ABI when it defines a + // frame pointer register. It may differ from the effective value of + // the FP register when that register is used in the JVM for other + // purposes (like compiled frames on some platforms). + // On other platforms, it is defined so that the stack area used by + // this frame goes from real_fp() to sp(). + intptr_t* real_fp() const; + // Deoptimization info, if needed (platform dependent). // Stored in the initial_info field of the unroll info, to be used by // the platform dependent deoptimization blobs. diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/globals.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -3826,10 +3826,6 @@ develop(bool, StressMethodHandleWalk, false, \ "Process all method handles with MethodHandleWalk") \ \ - diagnostic(bool, UseRicochetFrames, true, \ - "use ricochet stack frames for method handle combination, " \ - "if the platform supports them") \ - \ experimental(bool, TrustFinalNonStaticFields, false, \ "trust final non-static declarations for constant folding") \ \ diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/java.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -57,6 +57,8 @@ #include "runtime/task.hpp" #include "runtime/timer.hpp" #include "runtime/vm_operations.hpp" +#include "trace/tracing.hpp" +#include "trace/traceEventTypes.hpp" #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/histogram.hpp" @@ -502,6 +504,11 @@ if (JvmtiExport::should_post_thread_life()) { JvmtiExport::post_thread_end(thread); } + + EVENT_BEGIN(TraceEventThreadEnd, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(thread->threadObj()))); + // Always call even when there are not JVMTI environments yet, since environments // may be attached late and JVMTI must track phases of VM execution JvmtiExport::post_vm_death(); diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/mutexLocker.cpp --- a/src/share/vm/runtime/mutexLocker.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/mutexLocker.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -132,7 +132,13 @@ Monitor* GCTaskManager_lock = NULL; Mutex* Management_lock = NULL; -Monitor* Service_lock = NULL; +Monitor* Service_lock = NULL; +Mutex* Stacktrace_lock = NULL; + +Monitor* JfrQuery_lock = NULL; +Monitor* JfrMsg_lock = NULL; +Mutex* JfrBuffer_lock = NULL; +Mutex* JfrStream_lock = NULL; #define MAX_NUM_MUTEX 128 static Monitor * _mutex_array[MAX_NUM_MUTEX]; @@ -207,6 +213,7 @@ def(Patching_lock , Mutex , special, true ); // used for safepointing and code patching. def(ObjAllocPost_lock , Monitor, special, false); def(Service_lock , Monitor, special, true ); // used for service thread operations + def(Stacktrace_lock , Mutex, special, true ); // used for JFR stacktrace database def(JmethodIdCreation_lock , Mutex , leaf, true ); // used for creating jmethodIDs. def(SystemDictionary_lock , Monitor, leaf, true ); // lookups done by VM thread @@ -271,6 +278,11 @@ def(Debug3_lock , Mutex , nonleaf+4, true ); def(ProfileVM_lock , Monitor, nonleaf+4, false); // used for profiling of the VMThread def(CompileThread_lock , Monitor, nonleaf+5, false ); + + def(JfrQuery_lock , Monitor, nonleaf, true); // JFR locks, keep these in consecutive order + def(JfrMsg_lock , Monitor, nonleaf+2, true); + def(JfrBuffer_lock , Mutex, nonleaf+3, true); + def(JfrStream_lock , Mutex, nonleaf+4, true); } GCMutexLocker::GCMutexLocker(Monitor * mutex) { diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/mutexLocker.hpp --- a/src/share/vm/runtime/mutexLocker.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/mutexLocker.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -135,6 +135,12 @@ extern Mutex* Management_lock; // a lock used to serialize JVM management extern Monitor* Service_lock; // a lock used for service thread operation +extern Mutex* Stacktrace_lock; // used to guard access to the stacktrace table + +extern Monitor* JfrQuery_lock; // protects JFR use +extern Monitor* JfrMsg_lock; // protects JFR messaging +extern Mutex* JfrBuffer_lock; // protects JFR buffer operations +extern Mutex* JfrStream_lock; // protects JFR stream access // A MutexLocker provides mutual exclusion with respect to a given mutex // for the scope which contains the locker. The lock is an OS lock, not diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/os.cpp --- a/src/share/vm/runtime/os.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/os.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -1101,6 +1101,7 @@ "%/lib/jsse.jar:" "%/lib/jce.jar:" "%/lib/charsets.jar:" + "%/lib/jfr.jar:" #ifdef __APPLE__ "%/lib/JObjC.jar:" #endif diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/sharedRuntime.cpp --- a/src/share/vm/runtime/sharedRuntime.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/sharedRuntime.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -121,7 +121,6 @@ void SharedRuntime::generate_ricochet_blob() { if (!EnableInvokeDynamic) return; // leave it as a null -#ifndef TARGET_ARCH_NYI_6939861 // allocate space for the code ResourceMark rm; // setup code generation tools @@ -142,7 +141,6 @@ } _ricochet_blob = RicochetBlob::create(&buffer, bounce_offset, exception_offset, frame_size_in_words); -#endif } diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/thread.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -73,6 +73,7 @@ #include "services/attachListener.hpp" #include "services/management.hpp" #include "services/threadService.hpp" +#include "trace/traceEventTypes.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" #include "utilities/events.hpp" @@ -232,6 +233,7 @@ CHECK_UNHANDLED_OOPS_ONLY(_gc_locked_out_count = 0;) _jvmti_env_iteration_count = 0; set_allocated_bytes(0); + set_trace_buffer(NULL); _vm_operation_started_count = 0; _vm_operation_completed_count = 0; _current_pending_monitor = NULL; @@ -1512,6 +1514,10 @@ JvmtiExport::post_thread_start(this); } + EVENT_BEGIN(TraceEventThreadStart, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj()))); + // We call another function to do the rest so we are sure that the stack addresses used // from there will be lower than the stack base just computed thread_main_inner(); @@ -1641,6 +1647,15 @@ } } + // Called before the java thread exit since we want to read info + // from java_lang_Thread object + EVENT_BEGIN(TraceEventThreadEnd, event); + EVENT_COMMIT(event, + EVENT_SET(event, javalangthread, java_lang_Thread::thread_id(this->threadObj()))); + + // Call after last event on thread + EVENT_THREAD_EXIT(this); + // Call Thread.exit(). We try 3 times in case we got another Thread.stop during // the execution of the method. If that is not enough, then we don't really care. Thread.stop // is deprecated anyhow. @@ -3186,6 +3201,11 @@ return status; } + // Must be run after init_ft which initializes ft_enabled + if (TRACE_INITIALIZE() != JNI_OK) { + vm_exit_during_initialization("Failed to initialize tracing backend"); + } + // Should be done after the heap is fully created main_thread->cache_global_variables(); @@ -3423,6 +3443,10 @@ create_vm_init_libraries(); } + if (!TRACE_START()) { + vm_exit_during_initialization(Handle(THREAD, PENDING_EXCEPTION)); + } + // Notify JVMTI agents that VM initialization is complete - nop if no agents. JvmtiExport::post_vm_initialized(); diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/thread.hpp --- a/src/share/vm/runtime/thread.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/thread.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -41,6 +41,7 @@ #include "runtime/stubRoutines.hpp" #include "runtime/threadLocalStorage.hpp" #include "runtime/unhandledOops.hpp" +#include "trace/tracing.hpp" #include "utilities/exceptions.hpp" #include "utilities/top.hpp" #ifndef SERIALGC @@ -246,6 +247,8 @@ jlong _allocated_bytes; // Cumulative number of bytes allocated on // the Java heap + TRACE_BUFFER _trace_buffer; // Thread-local buffer for tracing + int _vm_operation_started_count; // VM_Operation support int _vm_operation_completed_count; // VM_Operation support @@ -414,6 +417,9 @@ return allocated_bytes; } + TRACE_BUFFER trace_buffer() { return _trace_buffer; } + void set_trace_buffer(TRACE_BUFFER buf) { _trace_buffer = buf; } + // VM operation support int vm_operation_ticket() { return ++_vm_operation_started_count; } int vm_operation_completed_count() { return _vm_operation_completed_count; } diff -r 1ac084126285 -r d851f3714641 src/share/vm/runtime/vm_operations.hpp --- a/src/share/vm/runtime/vm_operations.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/runtime/vm_operations.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -93,6 +93,7 @@ template(HeapWalkOperation) \ template(HeapIterateOperation) \ template(ReportJavaOutOfMemory) \ + template(JFRCheckpoint) \ template(Exit) \ class VM_Operation: public CHeapObj { diff -r 1ac084126285 -r d851f3714641 src/share/vm/trace/traceEventTypes.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/trace/traceEventTypes.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,30 @@ +/* + * 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP +#define SHARE_VM_TRACE_TRACE_EVENT_TYPES_HPP + +/* Empty, just a placeholder for tracing events */ + +#endif diff -r 1ac084126285 -r d851f3714641 src/share/vm/trace/traceMacros.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/trace/traceMacros.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_TRACE_TRACE_MACRO_HPP +#define SHARE_VM_TRACE_TRACE_MACRO_HPP + +#define EVENT_BEGIN(type, name) +#define EVENT_SET(name, field, value) +#define EVENT_COMMIT(name, ...) +#define EVENT_STARTED(name, time) +#define EVENT_ENDED(name, time) +#define EVENT_THREAD_EXIT(thread) + +#define TRACE_ENABLED 0 + +#define TRACE_INIT_ID(k) +#define TRACE_BUFFER void* + +#define TRACE_START() true +#define TRACE_INITIALIZE() 0 + +#endif diff -r 1ac084126285 -r d851f3714641 src/share/vm/trace/tracing.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/trace/tracing.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_TRACE_TRACING_HPP +#define SHARE_VM_TRACE_TRACING_HPP + +#include "trace/traceMacros.hpp" + +#endif diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/decoder.cpp --- a/src/share/vm/utilities/decoder.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/decoder.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -24,80 +24,85 @@ #include "precompiled.hpp" #include "prims/jvm.h" +#include "runtime/mutexLocker.hpp" #include "utilities/decoder.hpp" -Decoder::decoder_status Decoder::_decoder_status = Decoder::no_error; -bool Decoder::_initialized = false; - -#if !defined(_WINDOWS) && !defined(__APPLE__) - -// Implementation of common functionalities among Solaris and Linux -#include "utilities/elfFile.hpp" - -ElfFile* Decoder::_opened_elf_files = NULL; - -bool Decoder::can_decode_C_frame_in_vm() { - return true; -} +#if defined(_WINDOWS) + #include "decoder_windows.hpp" +#elif defined(__APPLE__) + #include "decoder_machO.hpp" +#else + #include "decoder_elf.hpp" +#endif -void Decoder::initialize() { - _initialized = true; -} +NullDecoder* Decoder::_decoder = NULL; +NullDecoder Decoder::_do_nothing_decoder; +Mutex* Decoder::_decoder_lock = new Mutex(Mutex::safepoint, + "DecoderLock"); -void Decoder::uninitialize() { - if (_opened_elf_files != NULL) { - delete _opened_elf_files; - _opened_elf_files = NULL; - } - _initialized = false; -} +// _decoder_lock should already acquired before enter this method +NullDecoder* Decoder::get_decoder() { + assert(_decoder_lock != NULL && _decoder_lock->owned_by_self(), + "Require DecoderLock to enter"); -Decoder::decoder_status Decoder::decode(address addr, const char* filepath, char *buf, int buflen, int *offset) { - if (_decoder_status != no_error) { - return _decoder_status; - } - - ElfFile* file = get_elf_file(filepath); - if (_decoder_status != no_error) { - return _decoder_status; + if (_decoder != NULL) { + return _decoder; } - const char* symbol = file->decode(addr, offset); - if (file->get_status() == out_of_memory) { - _decoder_status = out_of_memory; - return _decoder_status; - } else if (symbol != NULL) { - if (!demangle(symbol, buf, buflen)) { - jio_snprintf(buf, buflen, "%s", symbol); + // Decoder is a secondary service. Although, it is good to have, + // but we can live without it. +#if defined(_WINDOWS) + _decoder = new (std::nothrow) WindowsDecoder(); +#elif defined (__APPLE__) + _decoder = new (std::nothrow)MachODecoder(); +#else + _decoder = new (std::nothrow)ElfDecoder(); +#endif + + if (_decoder == NULL || _decoder->has_error()) { + if (_decoder != NULL) { + delete _decoder; } - return no_error; - } else { - return symbol_not_found; + _decoder = &_do_nothing_decoder; } + return _decoder; +} + +bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + NullDecoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + + return decoder->decode(addr, buf, buflen, offset, modulepath); } -ElfFile* Decoder::get_elf_file(const char* filepath) { - if (_decoder_status != no_error) { - return NULL; - } - ElfFile* file = _opened_elf_files; - while (file != NULL) { - if (file->same_elf_file(filepath)) { - return file; - } - file = file->m_next; +bool Decoder::demangle(const char* symbol, char* buf, int buflen) { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + NullDecoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + return decoder->demangle(symbol, buf, buflen); +} + +bool Decoder::can_decode_C_frame_in_vm() { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + NullDecoder* decoder = get_decoder(); + assert(decoder != NULL, "null decoder"); + return decoder->can_decode_C_frame_in_vm(); +} + +// shutdown real decoder and replace it with +// _do_nothing_decoder +void Decoder::shutdown() { + assert(_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_decoder_lock, true); + + if (_decoder != NULL && _decoder != &_do_nothing_decoder) { + delete _decoder; } - file = new ElfFile(filepath); - if (file == NULL) { - _decoder_status = out_of_memory; - } - if (_opened_elf_files != NULL) { - file->m_next = _opened_elf_files; - } - - _opened_elf_files = file; - return file; + _decoder = &_do_nothing_decoder; } -#endif diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/decoder.hpp --- a/src/share/vm/utilities/decoder.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/decoder.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -23,83 +23,78 @@ */ -#ifndef __DECODER_HPP -#define __DECODER_HPP +#ifndef SHARE_VM_UTILITIES_DECODER_HPP +#define SHARE_VM_UTILITIES_DECODER_HPP #include "memory/allocation.hpp" - -#ifdef _WINDOWS -#include -#include - -// functions needed for decoding symbols -typedef DWORD (WINAPI *pfn_SymSetOptions)(DWORD); -typedef BOOL (WINAPI *pfn_SymInitialize)(HANDLE, PCTSTR, BOOL); -typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); -typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); +#include "runtime/mutex.hpp" -#elif defined(__APPLE__) - -#else - -class ElfFile; - -#endif // _WINDOWS - - -class Decoder: public StackObj { - - public: +class NullDecoder: public CHeapObj { +public: // status code for decoding native C frame enum decoder_status { - no_error, // successfully decoded frames + not_available = -10, // real decoder is not available + no_error = 0, // successfully decoded frames out_of_memory, // out of memory file_invalid, // invalid elf file file_not_found, // could not found symbol file (on windows), such as jvm.pdb or jvm.map helper_not_found, // could not load dbghelp.dll (Windows only) helper_func_error, // decoding functions not found (Windows only) - helper_init_error, // SymInitialize failed (Windows only) - symbol_not_found // could not find the symbol + helper_init_error // SymInitialize failed (Windows only) }; - public: - Decoder() { initialize(); }; - ~Decoder() { uninitialize(); }; + NullDecoder() { + _decoder_status = not_available; + } + + ~NullDecoder() {}; + + virtual bool decode(address pc, char* buf, int buflen, int* offset, + const char* modulepath = NULL) { + return false; + } + + virtual bool demangle(const char* symbol, char* buf, int buflen) { + return false; + } + + virtual bool can_decode_C_frame_in_vm() const { + return false; + } + virtual decoder_status status() const { + return _decoder_status; + } + + virtual bool has_error() const { + return is_error(_decoder_status); + } + + static bool is_error(decoder_status status) { + return (status > 0); + } + +protected: + decoder_status _decoder_status; +}; + + +class Decoder: AllStatic { +public: + static bool decode(address pc, char* buf, int buflen, int* offset, const char* modulepath = NULL); + static bool demangle(const char* symbol, char* buf, int buflen); static bool can_decode_C_frame_in_vm(); - static void initialize(); - static void uninitialize(); - -#ifdef _WINDOWS - static decoder_status decode(address addr, char *buf, int buflen, int *offset); -#else - static decoder_status decode(address addr, const char* filepath, char *buf, int buflen, int *offset); -#endif - - static bool demangle(const char* symbol, char *buf, int buflen); - - static decoder_status get_status() { return _decoder_status; }; + static void shutdown(); +protected: + static NullDecoder* get_decoder(); -#if !defined(_WINDOWS) && !defined(__APPLE__) - private: - static ElfFile* get_elf_file(const char* filepath); -#endif // _WINDOWS - - - private: - static decoder_status _decoder_status; - static bool _initialized; +private: + static NullDecoder* _decoder; + static NullDecoder _do_nothing_decoder; -#ifdef _WINDOWS - static HMODULE _dbghelp_handle; - static bool _can_decode_in_vm; - static pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64; - static pfn_UndecorateSymbolName _pfnUndecorateSymbolName; -#elif __APPLE__ -#else - static ElfFile* _opened_elf_files; -#endif // _WINDOWS +protected: + static Mutex* _decoder_lock; }; -#endif // __DECODER_HPP +#endif // SHARE_VM_UTILITIES_DECODER_HPP diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/decoder_elf.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/decoder_elf.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" + +#if !defined(_WINDOWS) && !defined(__APPLE__) +#include "decoder_elf.hpp" + +ElfDecoder::~ElfDecoder() { + if (_opened_elf_files != NULL) { + delete _opened_elf_files; + _opened_elf_files = NULL; + } +} + +bool ElfDecoder::decode(address addr, char *buf, int buflen, int* offset, const char* filepath) { + assert(filepath, "null file path"); + assert(buf != NULL && buflen > 0, "Invalid buffer"); + if (has_error()) return false; + ElfFile* file = get_elf_file(filepath); + if (file == NULL) { + return false; + } + + if (!file->decode(addr, buf, buflen, offset)) { + return false; + } + if (buf[0] != '\0') { + demangle(buf, buf, buflen); + } + return true; +} + +ElfFile* ElfDecoder::get_elf_file(const char* filepath) { + ElfFile* file; + + file = _opened_elf_files; + while (file != NULL) { + if (file->same_elf_file(filepath)) { + return file; + } + file = file->next(); + } + + file = new (std::nothrow)ElfFile(filepath); + if (file != NULL) { + if (_opened_elf_files != NULL) { + file->set_next(_opened_elf_files); + } + _opened_elf_files = file; + } + + return file; +} +#endif diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/decoder_elf.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/utilities/decoder_elf.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_UTILITIES_DECODER_ELF_HPP +#define SHARE_VM_UTILITIES_DECODER_ELF_HPP + +#if !defined(_WINDOWS) && !defined(__APPLE__) + +#include "utilities/decoder.hpp" +#include "utilities/elfFile.hpp" + +class ElfDecoder: public NullDecoder { + +public: + ElfDecoder() { + _opened_elf_files = NULL; + _decoder_status = no_error; + } + ~ElfDecoder(); + + bool can_decode_C_frame_in_vm() const { return true; } + + bool demangle(const char* symbol, char *buf, int buflen); + bool decode(address addr, char *buf, int buflen, int* offset, const char* filepath = NULL); + +private: + ElfFile* get_elf_file(const char* filepath); + +private: + ElfFile* _opened_elf_files; +}; + +#endif +#endif // SHARE_VM_UTILITIES_DECODER_ELF_HPP diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/elfFile.cpp --- a/src/share/vm/utilities/elfFile.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/elfFile.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -44,7 +44,7 @@ m_string_tables = NULL; m_symbol_tables = NULL; m_next = NULL; - m_status = Decoder::no_error; + m_status = NullDecoder::no_error; int len = strlen(filepath) + 1; m_filepath = (const char*)os::malloc(len * sizeof(char)); @@ -54,10 +54,10 @@ if (m_file != NULL) { load_tables(); } else { - m_status = Decoder::file_not_found; + m_status = NullDecoder::file_not_found; } } else { - m_status = Decoder::out_of_memory; + m_status = NullDecoder::out_of_memory; } } @@ -96,41 +96,41 @@ bool ElfFile::load_tables() { assert(m_file, "file not open"); - assert(m_status == Decoder::no_error, "already in error"); + assert(!NullDecoder::is_error(m_status), "already in error"); // read elf file header if (fread(&m_elfHdr, sizeof(m_elfHdr), 1, m_file) != 1) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; return false; } if (!is_elf_file(m_elfHdr)) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; return false; } // walk elf file's section headers, and load string tables Elf_Shdr shdr; if (!fseek(m_file, m_elfHdr.e_shoff, SEEK_SET)) { - if (m_status != Decoder::no_error) return false; + if (NullDecoder::is_error(m_status)) return false; for (int index = 0; index < m_elfHdr.e_shnum; index ++) { if (fread((void*)&shdr, sizeof(Elf_Shdr), 1, m_file) != 1) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; return false; } // string table if (shdr.sh_type == SHT_STRTAB) { ElfStringTable* table = new (std::nothrow) ElfStringTable(m_file, shdr, index); if (table == NULL) { - m_status = Decoder::out_of_memory; + m_status = NullDecoder::out_of_memory; return false; } add_string_table(table); } else if (shdr.sh_type == SHT_SYMTAB || shdr.sh_type == SHT_DYNSYM) { ElfSymbolTable* table = new (std::nothrow) ElfSymbolTable(m_file, shdr); if (table == NULL) { - m_status = Decoder::out_of_memory; + m_status = NullDecoder::out_of_memory; return false; } add_symbol_table(table); @@ -140,32 +140,33 @@ return true; } -const char* ElfFile::decode(address addr, int* offset) { +bool ElfFile::decode(address addr, char* buf, int buflen, int* offset) { // something already went wrong, just give up - if (m_status != Decoder::no_error) { - return NULL; + if (NullDecoder::is_error(m_status)) { + return false; } - ElfSymbolTable* symbol_table = m_symbol_tables; int string_table_index; int pos_in_string_table; int off = INT_MAX; bool found_symbol = false; while (symbol_table != NULL) { - if (Decoder::no_error == symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { + if (symbol_table->lookup(addr, &string_table_index, &pos_in_string_table, &off)) { found_symbol = true; } symbol_table = symbol_table->m_next; } - if (!found_symbol) return NULL; + if (!found_symbol) return false; ElfStringTable* string_table = get_string_table(string_table_index); + if (string_table == NULL) { - m_status = Decoder::file_invalid; - return NULL; + m_status = NullDecoder::file_invalid; + return false; } if (offset) *offset = off; - return string_table->string_at(pos_in_string_table); + + return string_table->string_at(pos_in_string_table, buf, buflen); } diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/elfFile.hpp --- a/src/share/vm/utilities/elfFile.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/elfFile.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -22,8 +22,8 @@ * */ -#ifndef __ELF_FILE_HPP -#define __ELF_FILE_HPP +#ifndef SHARE_VM_UTILITIES_ELF_FILE_HPP +#define SHARE_VM_UTILITIES_ELF_FILE_HPP #if !defined(_WINDOWS) && !defined(__APPLE__) @@ -83,12 +83,12 @@ // part of code to be very defensive, and bait out if anything went wrong. class ElfFile: public CHeapObj { - friend class Decoder; + friend class ElfDecoder; public: ElfFile(const char* filepath); ~ElfFile(); - const char* decode(address addr, int* offset); + bool decode(address addr, char* buf, int buflen, int* offset); const char* filepath() { return m_filepath; } @@ -99,7 +99,7 @@ return (m_filepath && !strcmp(filepath, m_filepath)); } - Decoder::decoder_status get_status() { + NullDecoder::decoder_status get_status() { return m_status; } @@ -119,8 +119,9 @@ // return a string table at specified section index ElfStringTable* get_string_table(int index); - // look up an address and return the nearest symbol - const char* look_up(Elf_Shdr shdr, address addr, int* offset); +protected: + ElfFile* next() const { return m_next; } + void set_next(ElfFile* file) { m_next = file; } protected: ElfFile* m_next; @@ -131,17 +132,17 @@ FILE* m_file; // Elf header - Elf_Ehdr m_elfHdr; + Elf_Ehdr m_elfHdr; // symbol tables - ElfSymbolTable* m_symbol_tables; + ElfSymbolTable* m_symbol_tables; // string tables - ElfStringTable* m_string_tables; + ElfStringTable* m_string_tables; - Decoder::decoder_status m_status; + NullDecoder::decoder_status m_status; }; #endif // _WINDOWS -#endif // __ELF_FILE_HPP +#endif // SHARE_VM_UTILITIES_ELF_FILE_HPP diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/elfStringTable.cpp --- a/src/share/vm/utilities/elfStringTable.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/elfStringTable.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -38,7 +38,7 @@ m_index = index; m_next = NULL; m_file = file; - m_status = Decoder::no_error; + m_status = NullDecoder::no_error; // try to load the string table long cur_offset = ftell(file); @@ -48,7 +48,7 @@ if (fseek(file, shdr.sh_offset, SEEK_SET) || fread((void*)m_table, shdr.sh_size, 1, file) != 1 || fseek(file, cur_offset, SEEK_SET)) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; os::free((void*)m_table); m_table = NULL; } @@ -67,22 +67,23 @@ } } -const char* ElfStringTable::string_at(int pos) { - if (m_status != Decoder::no_error) { - return NULL; +bool ElfStringTable::string_at(int pos, char* buf, int buflen) { + if (NullDecoder::is_error(m_status)) { + return false; } if (m_table != NULL) { - return (const char*)(m_table + pos); + jio_snprintf(buf, buflen, "%s", (const char*)(m_table + pos)); + return true; } else { long cur_pos = ftell(m_file); if (cur_pos == -1 || fseek(m_file, m_shdr.sh_offset + pos, SEEK_SET) || - fread(m_symbol, 1, MAX_SYMBOL_LEN, m_file) <= 0 || + fread(buf, 1, buflen, m_file) <= 0 || fseek(m_file, cur_pos, SEEK_SET)) { - m_status = Decoder::file_invalid; - return NULL; + m_status = NullDecoder::file_invalid; + return false; } - return (const char*)m_symbol; + return true; } } diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/elfStringTable.hpp --- a/src/share/vm/utilities/elfStringTable.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/elfStringTable.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -22,8 +22,8 @@ * */ -#ifndef __ELF_STRING_TABLE_HPP -#define __ELF_STRING_TABLE_HPP +#ifndef SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP +#define SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP #if !defined(_WINDOWS) && !defined(__APPLE__) @@ -35,9 +35,6 @@ // The string table represents a string table section in an elf file. // Whenever there is enough memory, it will load whole string table as // one blob. Otherwise, it will load string from file when requested. - -#define MAX_SYMBOL_LEN 256 - class ElfStringTable: CHeapObj { friend class ElfFile; public: @@ -48,10 +45,10 @@ int index() { return m_index; }; // get string at specified offset - const char* string_at(int offset); + bool string_at(int offset, char* buf, int buflen); // get status code - Decoder::decoder_status get_status() { return m_status; }; + NullDecoder::decoder_status get_status() { return m_status; }; protected: ElfStringTable* m_next; @@ -69,13 +66,10 @@ // section header Elf_Shdr m_shdr; - // buffer for reading individual string - char m_symbol[MAX_SYMBOL_LEN]; - // error code - Decoder::decoder_status m_status; + NullDecoder::decoder_status m_status; }; -#endif // _WINDOWS +#endif // _WINDOWS and _APPLE -#endif // __ELF_STRING_TABLE_HPP +#endif // SHARE_VM_UTILITIES_ELF_STRING_TABLE_HPP diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/elfSymbolTable.cpp --- a/src/share/vm/utilities/elfSymbolTable.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/elfSymbolTable.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -34,7 +34,7 @@ m_symbols = NULL; m_next = NULL; m_file = file; - m_status = Decoder::no_error; + m_status = NullDecoder::no_error; // try to load the string table long cur_offset = ftell(file); @@ -45,16 +45,16 @@ if (fseek(file, shdr.sh_offset, SEEK_SET) || fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 || fseek(file, cur_offset, SEEK_SET)) { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; os::free(m_symbols); m_symbols = NULL; } } - if (m_status == Decoder::no_error) { + if (!NullDecoder::is_error(m_status)) { memcpy(&m_shdr, &shdr, sizeof(Elf_Shdr)); } } else { - m_status = Decoder::file_invalid; + m_status = NullDecoder::file_invalid; } } @@ -68,13 +68,13 @@ } } -Decoder::decoder_status ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) { +bool ElfSymbolTable::lookup(address addr, int* stringtableIndex, int* posIndex, int* offset) { assert(stringtableIndex, "null string table index pointer"); assert(posIndex, "null string table offset pointer"); assert(offset, "null offset pointer"); - if (m_status != Decoder::no_error) { - return m_status; + if (NullDecoder::is_error(m_status)) { + return false; } address pc = 0; @@ -97,8 +97,8 @@ long cur_pos; if ((cur_pos = ftell(m_file)) == -1 || fseek(m_file, m_shdr.sh_offset, SEEK_SET)) { - m_status = Decoder::file_invalid; - return m_status; + m_status = NullDecoder::file_invalid; + return false; } Elf_Sym sym; @@ -114,13 +114,13 @@ } } } else { - m_status = Decoder::file_invalid; - return m_status; + m_status = NullDecoder::file_invalid; + return false; } } fseek(m_file, cur_pos, SEEK_SET); } - return m_status; + return true; } #endif // _WINDOWS diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/elfSymbolTable.hpp --- a/src/share/vm/utilities/elfSymbolTable.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/elfSymbolTable.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2011, 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 @@ -22,8 +22,8 @@ * */ -#ifndef __ELF_SYMBOL_TABLE_HPP -#define __ELF_SYMBOL_TABLE_HPP +#ifndef SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP +#define SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP #if !defined(_WINDOWS) && !defined(__APPLE__) @@ -45,9 +45,9 @@ ~ElfSymbolTable(); // search the symbol that is nearest to the specified address. - Decoder::decoder_status lookup(address addr, int* stringtableIndex, int* posIndex, int* offset); + bool lookup(address addr, int* stringtableIndex, int* posIndex, int* offset); - Decoder::decoder_status get_status() { return m_status; }; + NullDecoder::decoder_status get_status() { return m_status; }; protected: ElfSymbolTable* m_next; @@ -62,9 +62,9 @@ // section header Elf_Shdr m_shdr; - Decoder::decoder_status m_status; + NullDecoder::decoder_status m_status; }; -#endif // _WINDOWS +#endif // _WINDOWS and _APPLE -#endif // __ELF_SYMBOL_TABLE_HPP +#endif // SHARE_VM_UTILITIES_ELF_SYMBOL_TABLE_HPP diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/globalDefinitions.hpp --- a/src/share/vm/utilities/globalDefinitions.hpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/globalDefinitions.hpp Wed Jan 25 19:26:35 2012 -0500 @@ -298,6 +298,11 @@ const juint max_juint = (juint)-1; // 0xFFFFFFFF largest juint const julong max_julong = (julong)-1; // 0xFF....FF largest julong +typedef jbyte s1; +typedef jshort s2; +typedef jint s4; +typedef jlong s8; + //---------------------------------------------------------------------------------------------------- // JVM spec restrictions diff -r 1ac084126285 -r d851f3714641 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Tue Jan 24 18:00:54 2012 -0500 +++ b/src/share/vm/utilities/vmError.cpp Wed Jan 25 19:26:35 2012 -0500 @@ -571,8 +571,6 @@ if (fr.pc()) { st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); - // initialize decoder to decode C frames - Decoder decoder; int count = 0; while (count++ < StackPrintLimit) {