# HG changeset patch # User fparain # Date 1329489289 28800 # Node ID d3384450b64967964468290c7c2534de5c8880d3 # Parent be398bba40e92ff7a955fd461f6eccbe9fe5ff85# Parent df4927a3b82e2ea98d3e34eb7a3687464cce1509 Merge diff -r be398bba40e9 -r d3384450b649 agent/src/os/linux/Makefile --- a/agent/src/os/linux/Makefile Fri Feb 17 13:23:29 2012 +0100 +++ b/agent/src/os/linux/Makefile Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2002, 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ LIBS = -lthread_db -CFLAGS = -c -fPIC -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) +CFLAGS = -c -fPIC -g -D_GNU_SOURCE -D$(ARCH) $(INCLUDES) -D_FILE_OFFSET_BITS=64 LIBSA = $(ARCH)/libsaproc.so diff -r be398bba40e9 -r d3384450b649 agent/src/os/linux/libproc_impl.c --- a/agent/src/os/linux/libproc_impl.c Fri Feb 17 13:23:29 2012 +0100 +++ b/agent/src/os/linux/libproc_impl.c Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -50,10 +50,6 @@ char alt_path[PATH_MAX + 1]; init_alt_root(); - fd = open(name, O_RDONLY); - if (fd >= 0) { - return fd; - } if (alt_root_len > 0) { strcpy(alt_path, alt_root); @@ -73,6 +69,11 @@ return fd; } } + } else { + fd = open(name, O_RDONLY); + if (fd >= 0) { + return fd; + } } return -1; diff -r be398bba40e9 -r d3384450b649 make/jprt.properties --- a/make/jprt.properties Fri Feb 17 13:23:29 2012 +0100 +++ b/make/jprt.properties Fri Feb 17 06:34:49 2012 -0800 @@ -38,7 +38,9 @@ # This tells jprt what default release we want to build -jprt.tools.default.release=${jprt.submit.release} +jprt.hotspot.default.release=jdk7 + +jprt.tools.default.release=${jprt.submit.option.release?${jprt.submit.option.release}:${jprt.hotspot.default.release}} # Disable syncing the source after builds and tests are done. @@ -52,126 +54,46 @@ # Define the Solaris platforms we want for the various releases jprt.my.solaris.sparc.jdk8=solaris_sparc_5.10 jprt.my.solaris.sparc.jdk7=solaris_sparc_5.10 -jprt.my.solaris.sparc.jdk7b107=solaris_sparc_5.10 -jprt.my.solaris.sparc.jdk7temp=solaris_sparc_5.10 -jprt.my.solaris.sparc.jdk6=solaris_sparc_5.8 -jprt.my.solaris.sparc.jdk6perf=solaris_sparc_5.8 -jprt.my.solaris.sparc.jdk6u10=solaris_sparc_5.8 -jprt.my.solaris.sparc.jdk6u14=solaris_sparc_5.8 -jprt.my.solaris.sparc.jdk6u18=solaris_sparc_5.8 -jprt.my.solaris.sparc.jdk6u20=solaris_sparc_5.8 -jprt.my.solaris.sparc.ejdk7=${jprt.my.solaris.sparc.jdk7} -jprt.my.solaris.sparc.ejdk6=${jprt.my.solaris.sparc.jdk6} jprt.my.solaris.sparc=${jprt.my.solaris.sparc.${jprt.tools.default.release}} jprt.my.solaris.sparcv9.jdk8=solaris_sparcv9_5.10 jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10 -jprt.my.solaris.sparcv9.jdk7b107=solaris_sparcv9_5.10 -jprt.my.solaris.sparcv9.jdk7temp=solaris_sparcv9_5.10 -jprt.my.solaris.sparcv9.jdk6=solaris_sparcv9_5.8 -jprt.my.solaris.sparcv9.jdk6perf=solaris_sparcv9_5.8 -jprt.my.solaris.sparcv9.jdk6u10=solaris_sparcv9_5.8 -jprt.my.solaris.sparcv9.jdk6u14=solaris_sparcv9_5.8 -jprt.my.solaris.sparcv9.jdk6u18=solaris_sparcv9_5.8 -jprt.my.solaris.sparcv9.jdk6u20=solaris_sparcv9_5.8 -jprt.my.solaris.sparcv9.ejdk7=${jprt.my.solaris.sparcv9.jdk7} -jprt.my.solaris.sparcv9.ejdk6=${jprt.my.solaris.sparcv9.jdk6} jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}} jprt.my.solaris.i586.jdk8=solaris_i586_5.10 jprt.my.solaris.i586.jdk7=solaris_i586_5.10 -jprt.my.solaris.i586.jdk7b107=solaris_i586_5.10 -jprt.my.solaris.i586.jdk7temp=solaris_i586_5.10 -jprt.my.solaris.i586.jdk6=solaris_i586_5.8 -jprt.my.solaris.i586.jdk6perf=solaris_i586_5.8 -jprt.my.solaris.i586.jdk6u10=solaris_i586_5.8 -jprt.my.solaris.i586.jdk6u14=solaris_i586_5.8 -jprt.my.solaris.i586.jdk6u18=solaris_i586_5.8 -jprt.my.solaris.i586.jdk6u20=solaris_i586_5.8 -jprt.my.solaris.i586.ejdk7=${jprt.my.solaris.i586.jdk7} -jprt.my.solaris.i586.ejdk6=${jprt.my.solaris.i586.jdk6} jprt.my.solaris.i586=${jprt.my.solaris.i586.${jprt.tools.default.release}} jprt.my.solaris.x64.jdk8=solaris_x64_5.10 jprt.my.solaris.x64.jdk7=solaris_x64_5.10 -jprt.my.solaris.x64.jdk7b107=solaris_x64_5.10 -jprt.my.solaris.x64.jdk7temp=solaris_x64_5.10 -jprt.my.solaris.x64.jdk6=solaris_x64_5.10 -jprt.my.solaris.x64.jdk6perf=solaris_x64_5.10 -jprt.my.solaris.x64.jdk6u10=solaris_x64_5.10 -jprt.my.solaris.x64.jdk6u14=solaris_x64_5.10 -jprt.my.solaris.x64.jdk6u18=solaris_x64_5.10 -jprt.my.solaris.x64.jdk6u20=solaris_x64_5.10 -jprt.my.solaris.x64.ejdk7=${jprt.my.solaris.x64.jdk7} -jprt.my.solaris.x64.ejdk6=${jprt.my.solaris.x64.jdk6} jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}} jprt.my.linux.i586.jdk8=linux_i586_2.6 jprt.my.linux.i586.jdk7=linux_i586_2.6 -jprt.my.linux.i586.jdk7b107=linux_i586_2.6 -jprt.my.linux.i586.jdk7temp=linux_i586_2.6 -jprt.my.linux.i586.jdk6=linux_i586_2.4 -jprt.my.linux.i586.jdk6perf=linux_i586_2.4 -jprt.my.linux.i586.jdk6u10=linux_i586_2.4 -jprt.my.linux.i586.jdk6u14=linux_i586_2.4 -jprt.my.linux.i586.jdk6u18=linux_i586_2.4 -jprt.my.linux.i586.jdk6u20=linux_i586_2.4 -jprt.my.linux.i586.ejdk7=linux_i586_2.6 -jprt.my.linux.i586.ejdk6=linux_i586_2.6 jprt.my.linux.i586=${jprt.my.linux.i586.${jprt.tools.default.release}} jprt.my.linux.x64.jdk8=linux_x64_2.6 jprt.my.linux.x64.jdk7=linux_x64_2.6 -jprt.my.linux.x64.jdk7b107=linux_x64_2.6 -jprt.my.linux.x64.jdk7temp=linux_x64_2.6 -jprt.my.linux.x64.jdk6=linux_x64_2.4 -jprt.my.linux.x64.jdk6perf=linux_x64_2.4 -jprt.my.linux.x64.jdk6u10=linux_x64_2.4 -jprt.my.linux.x64.jdk6u14=linux_x64_2.4 -jprt.my.linux.x64.jdk6u18=linux_x64_2.4 -jprt.my.linux.x64.jdk6u20=linux_x64_2.4 -jprt.my.linux.x64.ejdk7=${jprt.my.linux.x64.jdk7} -jprt.my.linux.x64.ejdk6=${jprt.my.linux.x64.jdk6} jprt.my.linux.x64=${jprt.my.linux.x64.${jprt.tools.default.release}} jprt.my.linux.ppc.jdk8=linux_ppc_2.6 jprt.my.linux.ppc.jdk7=linux_ppc_2.6 -jprt.my.linux.ppc.jdk7b107=linux_ppc_2.6 -jprt.my.linux.ppc.jdk7temp=linux_ppc_2.6 -jprt.my.linux.ppc.ejdk6=linux_ppc_2.6 -jprt.my.linux.ppc.ejdk7=linux_ppc_2.6 jprt.my.linux.ppc=${jprt.my.linux.ppc.${jprt.tools.default.release}} jprt.my.linux.ppcv2.jdk8=linux_ppcv2_2.6 jprt.my.linux.ppcv2.jdk7=linux_ppcv2_2.6 -jprt.my.linux.ppcv2.jdk7b107=linux_ppcv2_2.6 -jprt.my.linux.ppcv2.jdk7temp=linux_ppcv2_2.6 -jprt.my.linux.ppcv2.ejdk6=linux_ppcv2_2.6 -jprt.my.linux.ppcv2.ejdk7=linux_ppcv2_2.6 jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}} jprt.my.linux.ppcsflt.jdk8=linux_ppcsflt_2.6 jprt.my.linux.ppcsflt.jdk7=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt.jdk7b107=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt.jdk7temp=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt.ejdk6=linux_ppcsflt_2.6 -jprt.my.linux.ppcsflt.ejdk7=linux_ppcsflt_2.6 jprt.my.linux.ppcsflt=${jprt.my.linux.ppcsflt.${jprt.tools.default.release}} jprt.my.linux.armvfp.jdk8=linux_armvfp_2.6 jprt.my.linux.armvfp.jdk7=linux_armvfp_2.6 -jprt.my.linux.armvfp.jdk7b107=linux_armvfp_2.6 -jprt.my.linux.armvfp.jdk7temp=linux_armvfp_2.6 -jprt.my.linux.armvfp.ejdk6=linux_armvfp_2.6 -jprt.my.linux.armvfp.ejdk7=linux_armvfp_2.6 jprt.my.linux.armvfp=${jprt.my.linux.armvfp.${jprt.tools.default.release}} jprt.my.linux.armsflt.jdk8=linux_armsflt_2.6 jprt.my.linux.armsflt.jdk7=linux_armsflt_2.6 -jprt.my.linux.armsflt.jdk7b107=linux_armsflt_2.6 -jprt.my.linux.armsflt.jdk7temp=linux_armsflt_2.6 -jprt.my.linux.armsflt.ejdk6=linux_armsflt_2.6 -jprt.my.linux.armsflt.ejdk7=linux_armsflt_2.6 jprt.my.linux.armsflt=${jprt.my.linux.armsflt.${jprt.tools.default.release}} jprt.my.macosx.x64.jdk8=macosx_x64_10.7 @@ -180,30 +102,10 @@ jprt.my.windows.i586.jdk8=windows_i586_5.1 jprt.my.windows.i586.jdk7=windows_i586_5.1 -jprt.my.windows.i586.jdk7b107=windows_i586_5.0 -jprt.my.windows.i586.jdk7temp=windows_i586_5.0 -jprt.my.windows.i586.jdk6=windows_i586_5.0 -jprt.my.windows.i586.jdk6perf=windows_i586_5.0 -jprt.my.windows.i586.jdk6u10=windows_i586_5.0 -jprt.my.windows.i586.jdk6u14=windows_i586_5.0 -jprt.my.windows.i586.jdk6u18=windows_i586_5.0 -jprt.my.windows.i586.jdk6u20=windows_i586_5.0 -jprt.my.windows.i586.ejdk7=${jprt.my.windows.i586.jdk7} -jprt.my.windows.i586.ejdk6=${jprt.my.windows.i586.jdk6} jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}} jprt.my.windows.x64.jdk8=windows_x64_5.2 jprt.my.windows.x64.jdk7=windows_x64_5.2 -jprt.my.windows.x64.jdk7b107=windows_x64_5.2 -jprt.my.windows.x64.jdk7temp=windows_x64_5.2 -jprt.my.windows.x64.jdk6=windows_x64_5.2 -jprt.my.windows.x64.jdk6perf=windows_x64_5.2 -jprt.my.windows.x64.jdk6u10=windows_x64_5.2 -jprt.my.windows.x64.jdk6u14=windows_x64_5.2 -jprt.my.windows.x64.jdk6u18=windows_x64_5.2 -jprt.my.windows.x64.jdk6u20=windows_x64_5.2 -jprt.my.windows.x64.ejdk7=${jprt.my.windows.x64.jdk7} -jprt.my.windows.x64.ejdk6=${jprt.my.windows.x64.jdk6} jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}} # Standard list of jprt build targets for this source tree @@ -539,16 +441,6 @@ jprt.test.targets.jdk8=${jprt.test.targets.standard} jprt.test.targets.jdk7=${jprt.test.targets.standard} -jprt.test.targets.jdk7temp=${jprt.test.targets.standard} -jprt.test.targets.jdk7b105=${jprt.test.targets.standard} -jprt.test.targets.jdk6=${jprt.test.targets.standard} -jprt.test.targets.jdk6perf=${jprt.test.targets.standard} -jprt.test.targets.jdk6u10=${jprt.test.targets.standard} -jprt.test.targets.jdk6u14=${jprt.test.targets.standard} -jprt.test.targets.jdk6u18=${jprt.test.targets.standard} -jprt.test.targets.jdk6u20=${jprt.test.targets.standard} -jprt.test.targets.ejdk6=${jprt.test.targets.embedded} -jprt.test.targets.ejdk7=${jprt.test.targets.embedded} jprt.test.targets=${jprt.test.targets.${jprt.tools.default.release}} # The default test/Makefile targets that should be run @@ -593,15 +485,5 @@ jprt.make.rule.test.targets.jdk8=${jprt.make.rule.test.targets.standard} jprt.make.rule.test.targets.jdk7=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk7temp=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk7b107=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk6=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk6perf=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk6u10=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk6u14=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk6u18=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.jdk6u20=${jprt.make.rule.test.targets.standard} -jprt.make.rule.test.targets.ejdk6=${jprt.make.rule.test.targets.embedded} -jprt.make.rule.test.targets.ejdk7=${jprt.make.rule.test.targets.embedded} jprt.make.rule.test.targets=${jprt.make.rule.test.targets.${jprt.tools.default.release}} diff -r be398bba40e9 -r d3384450b649 make/linux/makefiles/saproc.make --- a/make/linux/makefiles/saproc.make Fri Feb 17 13:23:29 2012 +0100 +++ b/make/linux/makefiles/saproc.make Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -75,6 +75,7 @@ fi @echo Making SA debugger back-end... $(QUIETLY) $(CC) -D$(BUILDARCH) -D_GNU_SOURCE \ + -D_FILE_OFFSET_BITS=64 \ $(SYMFLAG) $(ARCHFLAG) $(SHARED_FLAG) $(PICFLAG) \ -I$(SASRCDIR) \ -I$(GENERATED) \ diff -r be398bba40e9 -r d3384450b649 src/cpu/sparc/vm/globals_sparc.hpp --- a/src/cpu/sparc/vm/globals_sparc.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/cpu/sparc/vm/globals_sparc.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -56,14 +56,15 @@ // Stack slots are 2X larger in LP64 than in the 32 bit VM. define_pd_global(intx, ThreadStackSize, 1024); define_pd_global(intx, VMThreadStackSize, 1024); +define_pd_global(intx, StackShadowPages, 10 DEBUG_ONLY(+1)); #else define_pd_global(intx, ThreadStackSize, 512); define_pd_global(intx, VMThreadStackSize, 512); +define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1)); #endif define_pd_global(intx, StackYellowPages, 2); define_pd_global(intx, StackRedPages, 1); -define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+1)); define_pd_global(intx, PreInflateSpin, 40); // Determined by running design center diff -r be398bba40e9 -r d3384450b649 src/cpu/x86/vm/globals_x86.hpp --- a/src/cpu/x86/vm/globals_x86.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/cpu/x86/vm/globals_x86.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -60,7 +60,7 @@ #ifdef AMD64 // Very large C++ stack frames using solaris-amd64 optimized builds // due to lack of optimization caused by C++ compiler bugs -define_pd_global(intx, StackShadowPages, SOLARIS_ONLY(20) NOT_SOLARIS(6) DEBUG_ONLY(+2)); +define_pd_global(intx, StackShadowPages, NOT_WIN64(20) WIN64_ONLY(6) DEBUG_ONLY(+2)); #else define_pd_global(intx, StackShadowPages, 3 DEBUG_ONLY(+5)); #endif // AMD64 diff -r be398bba40e9 -r d3384450b649 src/cpu/x86/vm/vm_version_x86.hpp --- a/src/cpu/x86/vm/vm_version_x86.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/cpu/x86/vm/vm_version_x86.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -249,13 +249,18 @@ enum { // AMD - CPU_FAMILY_AMD_11H = 17, + CPU_FAMILY_AMD_11H = 0x11, // Intel CPU_FAMILY_INTEL_CORE = 6, - CPU_MODEL_NEHALEM_EP = 26, - CPU_MODEL_WESTMERE_EP = 44, -// CPU_MODEL_IVYBRIDGE_EP = ??, TODO - get real value - CPU_MODEL_SANDYBRIDGE_EP = 45 + CPU_MODEL_NEHALEM = 0x1e, + CPU_MODEL_NEHALEM_EP = 0x1a, + CPU_MODEL_NEHALEM_EX = 0x2e, + CPU_MODEL_WESTMERE = 0x25, + CPU_MODEL_WESTMERE_EP = 0x2c, + CPU_MODEL_WESTMERE_EX = 0x2f, + CPU_MODEL_SANDYBRIDGE = 0x2a, + CPU_MODEL_SANDYBRIDGE_EP = 0x2d, + CPU_MODEL_IVYBRIDGE_EP = 0x3a } cpuExtendedFamily; // cpuid information block. All info derived from executing cpuid with @@ -325,7 +330,7 @@ uint32_t proc_name_4, proc_name_5, proc_name_6, proc_name_7; uint32_t proc_name_8, proc_name_9, proc_name_10,proc_name_11; - // cpuid function 0x80000005 //AMD L1, Intel reserved + // cpuid function 0x80000005 // AMD L1, Intel reserved uint32_t ext_cpuid5_eax; // unused currently uint32_t ext_cpuid5_ebx; // reserved ExtCpuid5Ex ext_cpuid5_ecx; // L1 data cache info (AMD) @@ -547,15 +552,15 @@ static bool is_intel_tsc_synched_at_init() { if (is_intel_family_core()) { uint32_t ext_model = extended_cpu_model(); - if (ext_model == CPU_MODEL_NEHALEM_EP || - ext_model == CPU_MODEL_WESTMERE_EP || -// TODO ext_model == CPU_MODEL_IVYBRIDGE_EP || - ext_model == CPU_MODEL_SANDYBRIDGE_EP) { - // 2-socket invtsc support. EX versions with 4 sockets are not - // guaranteed to synchronize tscs at initialization via a double - // handshake. The tscs can be explicitly set in software. Code - // that uses tsc values must be prepared for them to arbitrarily - // jump backward or forward. + if (ext_model == CPU_MODEL_NEHALEM_EP || + ext_model == CPU_MODEL_WESTMERE_EP || + ext_model == CPU_MODEL_SANDYBRIDGE_EP || + ext_model == CPU_MODEL_IVYBRIDGE_EP) { + // <= 2-socket invariant tsc support. EX versions are usually used + // in > 2-socket systems and likely don't synchronize tscs at + // initialization. + // Code that uses tsc values must be prepared for them to arbitrarily + // jump forward or backward. return true; } } diff -r be398bba40e9 -r d3384450b649 src/os/bsd/vm/decoder_machO.hpp --- a/src/os/bsd/vm/decoder_machO.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/os/bsd/vm/decoder_machO.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,9 @@ #include "utilities/decoder.hpp" -// Just a placehold for now -class MachODecoder: public NullDecoder { +// Just a placehold for now, a real implementation should derive +// from AbstractDecoder +class MachODecoder : public NullDecoder { public: MachODecoder() { } ~MachODecoder() { } diff -r be398bba40e9 -r d3384450b649 src/os/windows/vm/decoder_windows.hpp --- a/src/os/windows/vm/decoder_windows.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/os/windows/vm/decoder_windows.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -36,7 +36,7 @@ typedef BOOL (WINAPI *pfn_SymGetSymFromAddr64)(HANDLE, DWORD64, PDWORD64, PIMAGEHLP_SYMBOL64); typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWORD); -class WindowsDecoder: public NullDecoder { +class WindowsDecoder : public AbstractDecoder { public: WindowsDecoder(); diff -r be398bba40e9 -r d3384450b649 src/share/vm/classfile/vmSymbols.hpp --- a/src/share/vm/classfile/vmSymbols.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/classfile/vmSymbols.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -284,6 +284,7 @@ template(run_method_name, "run") \ template(exit_method_name, "exit") \ template(add_method_name, "add") \ + template(remove_method_name, "remove") \ template(parent_name, "parent") \ template(threads_name, "threads") \ template(groups_name, "groups") \ diff -r be398bba40e9 -r d3384450b649 src/share/vm/prims/jvmtiTagMap.cpp --- a/src/share/vm/prims/jvmtiTagMap.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/prims/jvmtiTagMap.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -2999,7 +2999,8 @@ char type = field->field_type(); if (!is_primitive_field_type(type)) { oop fld_o = o->obj_field(field->field_offset()); - if (fld_o != NULL) { + // ignore any objects that aren't visible to profiler + if (fld_o != NULL && ServiceUtil::visible_oop(fld_o)) { // reflection code may have a reference to a klassOop. // - see sun.reflect.UnsafeStaticFieldAccessorImpl and sun.misc.Unsafe if (fld_o->is_klass()) { diff -r be398bba40e9 -r d3384450b649 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/runtime/arguments.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -1370,12 +1370,9 @@ // by ergonomics. if (MaxHeapSize <= max_heap_for_compressed_oops()) { #if !defined(COMPILER1) || defined(TIERED) -// disable UseCompressedOops by default on MacOS X until 7118647 is fixed -#ifndef __APPLE__ if (FLAG_IS_DEFAULT(UseCompressedOops)) { FLAG_SET_ERGO(bool, UseCompressedOops, true); } -#endif // !__APPLE__ #endif #ifdef _WIN64 if (UseLargePages && UseCompressedOops) { diff -r be398bba40e9 -r d3384450b649 src/share/vm/runtime/dtraceJSDT.cpp --- a/src/share/vm/runtime/dtraceJSDT.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/runtime/dtraceJSDT.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -82,7 +82,7 @@ int handle = pd_activate((void*)probes, module_name, providers_count, providers); - if (handle <= 0) { + if (handle < 0) { delete probes; THROW_MSG_0(vmSymbols::java_lang_RuntimeException(), "Unable to register DTrace probes (internal error)."); diff -r be398bba40e9 -r d3384450b649 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/runtime/thread.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -3220,11 +3220,6 @@ 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(); @@ -3366,6 +3361,7 @@ initialize_class(vmSymbols::java_lang_ArithmeticException(), CHECK_0); initialize_class(vmSymbols::java_lang_StackOverflowError(), CHECK_0); initialize_class(vmSymbols::java_lang_IllegalMonitorStateException(), CHECK_0); + initialize_class(vmSymbols::java_lang_IllegalArgumentException(), CHECK_0); } else { warning("java.lang.OutOfMemoryError has not been initialized"); warning("java.lang.NullPointerException has not been initialized"); @@ -3373,6 +3369,7 @@ warning("java.lang.ArrayStoreException has not been initialized"); warning("java.lang.ArithmeticException has not been initialized"); warning("java.lang.StackOverflowError has not been initialized"); + warning("java.lang.IllegalArgumentException has not been initialized"); } } @@ -3402,6 +3399,11 @@ quicken_jni_functions(); + // Must be run after init_ft which initializes ft_enabled + if (TRACE_INITIALIZE() != JNI_OK) { + vm_exit_during_initialization("Failed to initialize tracing backend"); + } + // Set flag that basic initialization has completed. Used by exceptions and various // debug stuff, that does not work until all basic classes have been initialized. set_init_completed(); diff -r be398bba40e9 -r d3384450b649 src/share/vm/runtime/virtualspace.cpp --- a/src/share/vm/runtime/virtualspace.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/runtime/virtualspace.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -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 @@ -455,7 +455,7 @@ void ReservedSpace::protect_noaccess_prefix(const size_t size) { assert( (_noaccess_prefix != 0) == (UseCompressedOops && _base != NULL && - (size_t(_base + _size) > OopEncodingHeapMax) && + (Universe::narrow_oop_base() != NULL) && Universe::narrow_oop_use_implicit_null_checks()), "noaccess_prefix should be used only with non zero based compressed oops"); diff -r be398bba40e9 -r d3384450b649 src/share/vm/services/diagnosticArgument.cpp --- a/src/share/vm/services/diagnosticArgument.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/services/diagnosticArgument.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -28,9 +28,16 @@ #include "services/diagnosticArgument.hpp" void GenDCmdArgument::read_value(const char* str, size_t len, TRAPS) { - if (is_set()) { + /* NOTE:Some argument types doesn't require a value, + * for instance boolean arguments: "enableFeatureX". is + * equivalent to "enableFeatureX=true". In these cases, + * str will be null. This is perfectly valid. + * All argument types must perform null checks on str. + */ + + if (is_set() && !allow_multiple()) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Duplicates in diagnostic command arguments"); + "Duplicates in diagnostic command arguments\n"); } parse_value(str, len, CHECK); set_is_set(true); @@ -38,9 +45,9 @@ template <> void DCmdArgument::parse_value(const char* str, size_t len, TRAPS) { - if (sscanf(str, INT64_FORMAT, &_value) != 1) { + if (str == NULL || sscanf(str, INT64_FORMAT, &_value) != 1) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), - "Integer parsing error in diagnostic command arguments"); + "Integer parsing error in diagnostic command arguments\n"); } } @@ -89,16 +96,20 @@ template <> void DCmdArgument::parse_value(const char* str, size_t len, TRAPS) { - _value = NEW_C_HEAP_ARRAY(char, len+1); - strncpy(_value, str, len); - _value[len] = 0; + if (str == NULL) { + _value = NULL; + } else { + _value = NEW_C_HEAP_ARRAY(char, len+1); + strncpy(_value, str, len); + _value[len] = 0; + } } template <> void DCmdArgument::init_value(TRAPS) { - if (has_default()) { + if (has_default() && _default_string != NULL) { this->parse_value(_default_string, strlen(_default_string), THREAD); if (HAS_PENDING_EXCEPTION) { - fatal("Default string must be parsable"); + fatal("Default string must be parsable"); } } else { set_value(NULL); @@ -111,3 +122,153 @@ set_value(NULL); } } + +template <> void DCmdArgument::parse_value(const char* str, + size_t len, TRAPS) { + if (str == NULL) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Integer parsing error nanotime value: syntax error"); + } + + int argc = sscanf(str, INT64_FORMAT , &_value._time); + if (argc != 1) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Integer parsing error nanotime value: syntax error"); + } + size_t idx = 0; + while(idx < len && isdigit(str[idx])) { + idx++; + } + if (idx == len) { + // only accept missing unit if the value is 0 + if (_value._time != 0) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Integer parsing error nanotime value: unit required"); + } else { + _value._nanotime = 0; + strcpy(_value._unit, "ns"); + return; + } + } else if(len - idx > 2) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Integer parsing error nanotime value: illegal unit"); + } else { + strncpy(_value._unit, &str[idx], len - idx); + /*Write an extra null termination. This is safe because _value._unit + * is declared as char[3], and length is checked to be not larger than + * two above. Also, this is necessary, since length might be 1, and the + * default value already in the string is ns, which is two chars. + */ + _value._unit[len-idx] = '\0'; + } + + if (strcmp(_value._unit, "ns") == 0) { + _value._nanotime = _value._time; + } else if (strcmp(_value._unit, "us") == 0) { + _value._nanotime = _value._time * 1000; + } else if (strcmp(_value._unit, "ms") == 0) { + _value._nanotime = _value._time * 1000 * 1000; + } else if (strcmp(_value._unit, "s") == 0) { + _value._nanotime = _value._time * 1000 * 1000 * 1000; + } else if (strcmp(_value._unit, "m") == 0) { + _value._nanotime = _value._time * 60 * 1000 * 1000 * 1000; + } else if (strcmp(_value._unit, "h") == 0) { + _value._nanotime = _value._time * 60 * 60 * 1000 * 1000 * 1000; + } else if (strcmp(_value._unit, "d") == 0) { + _value._nanotime = _value._time * 24 * 60 * 60 * 1000 * 1000 * 1000; + } else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Integer parsing error nanotime value: illegal unit"); + } +} + +template <> void DCmdArgument::init_value(TRAPS) { + if (has_default()) { + this->parse_value(_default_string, strlen(_default_string), THREAD); + if (HAS_PENDING_EXCEPTION) { + fatal("Default string must be parsable"); + } + } else { + _value._time = 0; + _value._nanotime = 0; + strcmp(_value._unit, "ns"); + } +} + +template <> void DCmdArgument::destroy_value() { } + +// WARNING StringArrayArgument can only be used as an option, it cannot be +// used as an argument with the DCmdParser + +template <> void DCmdArgument::parse_value(const char* str, + size_t len, TRAPS) { + _value->add(str,len); +} + +template <> void DCmdArgument::init_value(TRAPS) { + _value = new StringArrayArgument(); + _allow_multiple = true; + if (has_default()) { + fatal("StringArrayArgument cannot have default value"); + } +} + +template <> void DCmdArgument::destroy_value() { + if (_value != NULL) { + delete _value; + set_value(NULL); + } +} + +template <> void DCmdArgument::parse_value(const char* str, + size_t len, TRAPS) { + if (str == NULL) { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Integer parsing error nanotime value: syntax error"); + } + + if (*str == '-') { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Parsing error memory size value: negative values not allowed"); + } + int res = sscanf(str, UINT64_FORMAT "%c", &_value._val, &_value._multiplier); + if (res == 2) { + switch (_value._multiplier) { + case 'k': case 'K': + _value._size = _value._val * 1024; + break; + case 'm': case 'M': + _value._size = _value._val * 1024 * 1024; + break; + case 'g': case 'G': + _value._size = _value._val * 1024 * 1024 * 1024; + break; + default: + _value._size = _value._val; + _value._multiplier = ' '; + //default case should be to break with no error, since user + //can write size in bytes, or might have a delimiter and next arg + break; + } + } else if (res == 1) { + _value._size = _value._val; + } else { + THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), + "Parsing error memory size value: invalid value"); + } +} + +template <> void DCmdArgument::init_value(TRAPS) { + if (has_default()) { + this->parse_value(_default_string, strlen(_default_string), THREAD); + if (HAS_PENDING_EXCEPTION) { + fatal("Default string must be parsable"); + } + } else { + _value._size = 0; + _value._val = 0; + _value._multiplier = ' '; + } +} + +template <> void DCmdArgument::destroy_value() { } diff -r be398bba40e9 -r d3384450b649 src/share/vm/services/diagnosticArgument.hpp --- a/src/share/vm/services/diagnosticArgument.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/services/diagnosticArgument.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,49 @@ #include "runtime/thread.hpp" #include "utilities/exceptions.hpp" +class StringArrayArgument : public CHeapObj { +private: + GrowableArray* _array; +public: + StringArrayArgument() { + _array = new(ResourceObj::C_HEAP)GrowableArray(32, true); + assert(_array != NULL, "Sanity check"); + } + void add(const char* str, size_t len) { + if (str != NULL) { + char* ptr = NEW_C_HEAP_ARRAY(char, len+1); + strncpy(ptr, str, len); + ptr[len] = 0; + _array->append(ptr); + } + } + GrowableArray* array() { + return _array; + } + ~StringArrayArgument() { + for (int i=0; i<_array->length(); i++) { + if(_array->at(i) != NULL) { // Safety check + FREE_C_HEAP_ARRAY(char, _array->at(i)); + } + } + delete _array; + } +}; + +class NanoTimeArgument { +public: + jlong _nanotime; + jlong _time; + char _unit[3]; +}; + +class MemorySizeArgument { +public: + u8 _size; + u8 _val; + char _multiplier; +}; + class GenDCmdArgument : public ResourceObj { protected: GenDCmdArgument* _next; @@ -40,6 +83,7 @@ const char* _default_string; bool _is_set; bool _is_mandatory; + bool _allow_multiple; GenDCmdArgument(const char* name, const char* description, const char* type, const char* default_string, bool mandatory) { _name = name; @@ -48,6 +92,7 @@ _default_string = default_string; _is_mandatory = mandatory; _is_set = false; + _allow_multiple = false; }; public: const char* name() { return _name; } @@ -56,6 +101,7 @@ const char* default_string() { return _default_string; } bool is_set() { return _is_set; } void set_is_set(bool b) { _is_set = b; } + bool allow_multiple() { return _allow_multiple; } bool is_mandatory() { return _is_mandatory; } bool has_value() { return _is_set || _default_string != NULL; } bool has_default() { return _default_string != NULL; } diff -r be398bba40e9 -r d3384450b649 src/share/vm/services/diagnosticFramework.cpp --- a/src/share/vm/services/diagnosticFramework.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/services/diagnosticFramework.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,7 +61,7 @@ bool DCmdArgIter::next(TRAPS) { if (_len == 0) return false; // skipping spaces - while (_cursor < _len - 1 && isspace(_buffer[_cursor])) { + while (_cursor < _len - 1 && _buffer[_cursor] == _delim) { _cursor++; } // handling end of command line diff -r be398bba40e9 -r d3384450b649 src/share/vm/services/diagnosticFramework.hpp --- a/src/share/vm/services/diagnosticFramework.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/services/diagnosticFramework.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -195,6 +195,7 @@ DCmdParser() { _options = NULL; _arguments_list = NULL; + _delim = ' '; } void add_dcmd_option(GenDCmdArgument* arg); void add_dcmd_argument(GenDCmdArgument* arg); diff -r be398bba40e9 -r d3384450b649 src/share/vm/services/gcNotifier.cpp --- a/src/share/vm/services/gcNotifier.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/services/gcNotifier.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -180,17 +180,43 @@ } void GCNotifier::sendNotification(TRAPS) { + GCNotifier::sendNotificationInternal(THREAD); + // Clearing pending exception to avoid premature termination of + // the service thread + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } +} + +class NotificationMark : public StackObj { + // This class is used in GCNotifier::sendNotificationInternal to ensure that + // the GCNotificationRequest object is properly cleaned up, whatever path + // is used to exit the method. + GCNotificationRequest* _request; +public: + NotificationMark(GCNotificationRequest* r) { + _request = r; + } + ~NotificationMark() { + assert(_request != NULL, "Sanity check"); + delete _request; + } +}; + +void GCNotifier::sendNotificationInternal(TRAPS) { ResourceMark rm(THREAD); + HandleMark hm(THREAD); GCNotificationRequest *request = getRequest(); - if(request != NULL) { - Handle objGcInfo = createGcInfo(request->gcManager,request->gcStatInfo,THREAD); + if (request != NULL) { + NotificationMark nm(request); + Handle objGcInfo = createGcInfo(request->gcManager, request->gcStatInfo, THREAD); Handle objName = java_lang_String::create_from_platform_dependent_str(request->gcManager->name(), CHECK); Handle objAction = java_lang_String::create_from_platform_dependent_str(request->gcAction, CHECK); Handle objCause = java_lang_String::create_from_platform_dependent_str(request->gcCause, CHECK); klassOop k = Management::sun_management_GarbageCollectorImpl_klass(CHECK); - instanceKlassHandle gc_mbean_klass (THREAD, k); + instanceKlassHandle gc_mbean_klass(THREAD, k); instanceOop gc_mbean = request->gcManager->get_memory_manager_instance(THREAD); instanceHandle gc_mbean_h(THREAD, gc_mbean); @@ -213,11 +239,6 @@ vmSymbols::createGCNotification_signature(), &args, CHECK); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } - - delete request; } } diff -r be398bba40e9 -r d3384450b649 src/share/vm/services/gcNotifier.hpp --- a/src/share/vm/services/gcNotifier.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/services/gcNotifier.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,7 @@ static GCNotificationRequest *last_request; static void addRequest(GCNotificationRequest *request); static GCNotificationRequest *getRequest(); + static void sendNotificationInternal(TRAPS); public: static void pushNotification(GCMemoryManager *manager, const char *action, const char *cause); static bool has_event(); diff -r be398bba40e9 -r d3384450b649 src/share/vm/utilities/decoder.cpp --- a/src/share/vm/utilities/decoder.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/utilities/decoder.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -25,7 +25,9 @@ #include "precompiled.hpp" #include "prims/jvm.h" #include "runtime/mutexLocker.hpp" +#include "runtime/os.hpp" #include "utilities/decoder.hpp" +#include "utilities/vmError.hpp" #if defined(_WINDOWS) #include "decoder_windows.hpp" @@ -35,74 +37,94 @@ #include "decoder_elf.hpp" #endif -NullDecoder* Decoder::_decoder = NULL; -NullDecoder Decoder::_do_nothing_decoder; -Mutex* Decoder::_decoder_lock = new Mutex(Mutex::safepoint, - "DecoderLock"); +AbstractDecoder* Decoder::_shared_decoder = NULL; +AbstractDecoder* Decoder::_error_handler_decoder = NULL; +NullDecoder Decoder::_do_nothing_decoder; +Mutex* Decoder::_shared_decoder_lock = new Mutex(Mutex::native, + "SharedDecoderLock"); -// _decoder_lock should already acquired before enter this method -NullDecoder* Decoder::get_decoder() { - assert(_decoder_lock != NULL && _decoder_lock->owned_by_self(), +AbstractDecoder* Decoder::get_shared_instance() { + assert(_shared_decoder_lock != NULL && _shared_decoder_lock->owned_by_self(), "Require DecoderLock to enter"); - if (_decoder != NULL) { - return _decoder; + if (_shared_decoder == NULL) { + _shared_decoder = create_decoder(); } + return _shared_decoder; +} - // Decoder is a secondary service. Although, it is good to have, - // but we can live without it. +AbstractDecoder* Decoder::get_error_handler_instance() { + if (_error_handler_decoder == NULL) { + _error_handler_decoder = create_decoder(); + } + return _error_handler_decoder; +} + + +AbstractDecoder* Decoder::create_decoder() { + AbstractDecoder* decoder; #if defined(_WINDOWS) - _decoder = new (std::nothrow) WindowsDecoder(); + decoder = new (std::nothrow) WindowsDecoder(); #elif defined (__APPLE__) - _decoder = new (std::nothrow)MachODecoder(); + decoder = new (std::nothrow)MachODecoder(); #else - _decoder = new (std::nothrow)ElfDecoder(); + decoder = new (std::nothrow)ElfDecoder(); #endif - if (_decoder == NULL || _decoder->has_error()) { - if (_decoder != NULL) { - delete _decoder; + if (decoder == NULL || decoder->has_error()) { + if (decoder != NULL) { + delete decoder; } - _decoder = &_do_nothing_decoder; + decoder = &_do_nothing_decoder; } - return _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(_shared_decoder_lock != NULL, "Just check"); + bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid; + MutexLockerEx locker(error_handling_thread ? NULL : _shared_decoder_lock, true); + AbstractDecoder* decoder = error_handling_thread ? + get_error_handler_instance(): get_shared_instance(); assert(decoder != NULL, "null decoder"); return decoder->decode(addr, buf, buflen, offset, modulepath); } 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(_shared_decoder_lock != NULL, "Just check"); + bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid; + MutexLockerEx locker(error_handling_thread ? NULL : _shared_decoder_lock, true); + AbstractDecoder* decoder = error_handling_thread ? + get_error_handler_instance(): get_shared_instance(); 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(_shared_decoder_lock != NULL, "Just check"); + bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid; + MutexLockerEx locker(error_handling_thread ? NULL : _shared_decoder_lock, true); + AbstractDecoder* decoder = error_handling_thread ? + get_error_handler_instance(): get_shared_instance(); assert(decoder != NULL, "null decoder"); return decoder->can_decode_C_frame_in_vm(); } -// shutdown real decoder and replace it with -// _do_nothing_decoder +/* + * Shutdown shared decoder and replace it with + * _do_nothing_decoder. Do nothing with error handler + * instance, since the JVM is going down. + */ void Decoder::shutdown() { - assert(_decoder_lock != NULL, "Just check"); - MutexLockerEx locker(_decoder_lock, true); + assert(_shared_decoder_lock != NULL, "Just check"); + MutexLockerEx locker(_shared_decoder_lock, true); - if (_decoder != NULL && _decoder != &_do_nothing_decoder) { - delete _decoder; + if (_shared_decoder != NULL && + _shared_decoder != &_do_nothing_decoder) { + delete _shared_decoder; } - _decoder = &_do_nothing_decoder; + _shared_decoder = &_do_nothing_decoder; } diff -r be398bba40e9 -r d3384450b649 src/share/vm/utilities/decoder.hpp --- a/src/share/vm/utilities/decoder.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/utilities/decoder.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -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 @@ -29,7 +29,7 @@ #include "memory/allocation.hpp" #include "runtime/mutex.hpp" -class NullDecoder: public CHeapObj { +class AbstractDecoder : public CHeapObj { public: // status code for decoding native C frame enum decoder_status { @@ -43,6 +43,34 @@ helper_init_error // SymInitialize failed (Windows only) }; + // decode an pc address to corresponding function name and an offset from the beginning of + // the function + virtual bool decode(address pc, char* buf, int buflen, int* offset, + const char* modulepath = NULL) = 0; + // demangle a C++ symbol + virtual bool demangle(const char* symbol, char* buf, int buflen) = 0; + // if the decoder can decode symbols in vm + virtual bool can_decode_C_frame_in_vm() const = 0; + + 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; +}; + +// Do nothing decoder +class NullDecoder : public AbstractDecoder { +public: NullDecoder() { _decoder_status = not_available; } @@ -61,40 +89,34 @@ 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 { +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(); + // shutdown shared instance static void shutdown(); protected: - static NullDecoder* get_decoder(); + // shared decoder instance, _shared_instance_lock is needed + static AbstractDecoder* get_shared_instance(); + // a private instance for error handler. Error handler can be + // triggered almost everywhere, including signal handler, where + // no lock can be taken. So the shared decoder can not be used + // in this scenario. + static AbstractDecoder* get_error_handler_instance(); + static AbstractDecoder* create_decoder(); private: - static NullDecoder* _decoder; - static NullDecoder _do_nothing_decoder; + static AbstractDecoder* _shared_decoder; + static AbstractDecoder* _error_handler_decoder; + static NullDecoder _do_nothing_decoder; protected: - static Mutex* _decoder_lock; + static Mutex* _shared_decoder_lock; }; #endif // SHARE_VM_UTILITIES_DECODER_HPP diff -r be398bba40e9 -r d3384450b649 src/share/vm/utilities/decoder_elf.hpp --- a/src/share/vm/utilities/decoder_elf.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/utilities/decoder_elf.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ #include "utilities/decoder.hpp" #include "utilities/elfFile.hpp" -class ElfDecoder: public NullDecoder { +class ElfDecoder : public AbstractDecoder { public: ElfDecoder() { diff -r be398bba40e9 -r d3384450b649 src/share/vm/utilities/preserveException.cpp --- a/src/share/vm/utilities/preserveException.cpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/utilities/preserveException.cpp Fri Feb 17 06:34:49 2012 -0800 @@ -32,9 +32,9 @@ thread = Thread::current(); _thread = thread; _preserved_exception_oop = Handle(thread, _thread->pending_exception()); - _thread->clear_pending_exception(); // Needed to avoid infinite recursion _preserved_exception_line = _thread->exception_line(); _preserved_exception_file = _thread->exception_file(); + _thread->clear_pending_exception(); // Needed to avoid infinite recursion } diff -r be398bba40e9 -r d3384450b649 src/share/vm/utilities/vmError.hpp --- a/src/share/vm/utilities/vmError.hpp Fri Feb 17 13:23:29 2012 +0100 +++ b/src/share/vm/utilities/vmError.hpp Fri Feb 17 06:34:49 2012 -0800 @@ -27,11 +27,12 @@ #include "utilities/globalDefinitions.hpp" - +class Decoder; class VM_ReportJavaOutOfMemory; class VMError : public StackObj { friend class VM_ReportJavaOutOfMemory; + friend class Decoder; enum ErrorType { internal_error = 0xe0000000,