# HG changeset patch # User amurillo # Date 1373673219 25200 # Node ID 2b9946e10587f74ef75ae8145bea484df4a2738b # Parent 1a3390aa83264261acb8428622c6be5b16250a1a# Parent 0f631140d13b735758263506dfc2973d458b6fdf Merge diff -r 1a3390aa8326 -r 2b9946e10587 agent/src/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java Thu Jul 11 10:13:37 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java Fri Jul 12 16:53:39 2013 -0700 @@ -49,7 +49,6 @@ higherDimension = new MetadataField(type.getAddressField("_higher_dimension"), 0); lowerDimension = new MetadataField(type.getAddressField("_lower_dimension"), 0); vtableLen = new CIntField(type.getCIntegerField("_vtable_len"), 0); - allocSize = new CIntField(type.getCIntegerField("_alloc_size"), 0); componentMirror = new OopField(type.getOopField("_component_mirror"), 0); javaLangCloneableName = null; javaLangObjectName = null; @@ -64,7 +63,6 @@ private static MetadataField higherDimension; private static MetadataField lowerDimension; private static CIntField vtableLen; - private static CIntField allocSize; private static OopField componentMirror; public Klass getJavaSuper() { @@ -76,7 +74,6 @@ public Klass getHigherDimension() { return (Klass) higherDimension.getValue(this); } public Klass getLowerDimension() { return (Klass) lowerDimension.getValue(this); } public long getVtableLen() { return vtableLen.getValue(this); } - public long getAllocSize() { return allocSize.getValue(this); } public Oop getComponentMirror() { return componentMirror.getValue(this); } // constant class names - javaLangCloneable, javaIoSerializable, javaLangObject @@ -147,7 +144,6 @@ visitor.doMetadata(higherDimension, true); visitor.doMetadata(lowerDimension, true); visitor.doCInt(vtableLen, true); - visitor.doCInt(allocSize, true); visitor.doOop(componentMirror, true); } } diff -r 1a3390aa8326 -r 2b9946e10587 agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java --- a/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java Thu Jul 11 10:13:37 2013 -0700 +++ b/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java Fri Jul 12 16:53:39 2013 -0700 @@ -57,7 +57,6 @@ accessFlags = new CIntField(type.getCIntegerField("_access_flags"), 0); subklass = new MetadataField(type.getAddressField("_subklass"), 0); nextSibling = new MetadataField(type.getAddressField("_next_sibling"), 0); - allocCount = new CIntField(type.getCIntegerField("_alloc_count"), 0); LH_INSTANCE_SLOW_PATH_BIT = db.lookupIntConstant("Klass::_lh_instance_slow_path_bit").intValue(); LH_LOG2_ELEMENT_SIZE_SHIFT = db.lookupIntConstant("Klass::_lh_log2_element_size_shift").intValue(); @@ -87,7 +86,6 @@ private static CIntField accessFlags; private static MetadataField subklass; private static MetadataField nextSibling; - private static CIntField allocCount; private Address getValue(AddressField field) { return addr.getAddressAt(field.getOffset()); @@ -108,7 +106,6 @@ public AccessFlags getAccessFlagsObj(){ return new AccessFlags(getAccessFlags()); } public Klass getSubklassKlass() { return (Klass) subklass.getValue(this); } public Klass getNextSiblingKlass() { return (Klass) nextSibling.getValue(this); } - public long getAllocCount() { return allocCount.getValue(this); } // computed access flags - takes care of inner classes etc. // This is closer to actual source level than getAccessFlags() etc. @@ -172,7 +169,6 @@ visitor.doCInt(accessFlags, true); visitor.doMetadata(subklass, true); visitor.doMetadata(nextSibling, true); - visitor.doCInt(allocCount, true); } public long getObjectSize() { diff -r 1a3390aa8326 -r 2b9946e10587 make/bsd/makefiles/mapfile-vers-debug --- a/make/bsd/makefiles/mapfile-vers-debug Thu Jul 11 10:13:37 2013 -0700 +++ b/make/bsd/makefiles/mapfile-vers-debug Fri Jul 12 16:53:39 2013 -0700 @@ -221,7 +221,6 @@ _JVM_SetLength _JVM_SetNativeThreadName _JVM_SetPrimitiveArrayElement - _JVM_SetProtectionDomain _JVM_SetSockOpt _JVM_SetThreadPriority _JVM_Sleep diff -r 1a3390aa8326 -r 2b9946e10587 make/bsd/makefiles/mapfile-vers-product --- a/make/bsd/makefiles/mapfile-vers-product Thu Jul 11 10:13:37 2013 -0700 +++ b/make/bsd/makefiles/mapfile-vers-product Fri Jul 12 16:53:39 2013 -0700 @@ -221,7 +221,6 @@ _JVM_SetLength _JVM_SetNativeThreadName _JVM_SetPrimitiveArrayElement - _JVM_SetProtectionDomain _JVM_SetSockOpt _JVM_SetThreadPriority _JVM_Sleep diff -r 1a3390aa8326 -r 2b9946e10587 make/hotspot_version --- a/make/hotspot_version Thu Jul 11 10:13:37 2013 -0700 +++ b/make/hotspot_version Fri Jul 12 16:53:39 2013 -0700 @@ -35,7 +35,7 @@ HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=40 +HS_BUILD_NUMBER=41 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff -r 1a3390aa8326 -r 2b9946e10587 make/linux/makefiles/mapfile-vers-debug --- a/make/linux/makefiles/mapfile-vers-debug Thu Jul 11 10:13:37 2013 -0700 +++ b/make/linux/makefiles/mapfile-vers-debug Fri Jul 12 16:53:39 2013 -0700 @@ -223,7 +223,6 @@ JVM_SetLength; JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; - JVM_SetProtectionDomain; JVM_SetSockOpt; JVM_SetThreadPriority; JVM_Sleep; diff -r 1a3390aa8326 -r 2b9946e10587 make/linux/makefiles/mapfile-vers-product --- a/make/linux/makefiles/mapfile-vers-product Thu Jul 11 10:13:37 2013 -0700 +++ b/make/linux/makefiles/mapfile-vers-product Fri Jul 12 16:53:39 2013 -0700 @@ -223,7 +223,6 @@ JVM_SetLength; JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; - JVM_SetProtectionDomain; JVM_SetSockOpt; JVM_SetThreadPriority; JVM_Sleep; diff -r 1a3390aa8326 -r 2b9946e10587 make/solaris/makefiles/mapfile-vers --- a/make/solaris/makefiles/mapfile-vers Thu Jul 11 10:13:37 2013 -0700 +++ b/make/solaris/makefiles/mapfile-vers Fri Jul 12 16:53:39 2013 -0700 @@ -223,7 +223,6 @@ JVM_SetLength; JVM_SetNativeThreadName; JVM_SetPrimitiveArrayElement; - JVM_SetProtectionDomain; JVM_SetSockOpt; JVM_SetThreadPriority; JVM_Sleep; diff -r 1a3390aa8326 -r 2b9946e10587 src/os/bsd/vm/os_bsd.cpp --- a/src/os/bsd/vm/os_bsd.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/bsd/vm/os_bsd.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -1234,12 +1234,13 @@ Dl_info dlinfo; if (libjvm_base_addr == NULL) { - dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo); - libjvm_base_addr = (address)dlinfo.dli_fbase; + if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) { + libjvm_base_addr = (address)dlinfo.dli_fbase; + } assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm"); } - if (dladdr((void *)addr, &dlinfo)) { + if (dladdr((void *)addr, &dlinfo) != 0) { if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true; } @@ -1251,35 +1252,40 @@ bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + Dl_info dlinfo; char localbuf[MACH_MAXSYMLEN]; - // dladdr will find names of dynamic functions only, but does - // it set dli_fbase with mach_header address when it "fails" ? - if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) { - if (buf != NULL) { - if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { + if (dladdr((void*)addr, &dlinfo) != 0) { + // see if we have a matching symbol + if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) { + if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; + return true; + } + // no matching symbol so try for just file info + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) { + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), + buf, buflen, offset, dlinfo.dli_fname)) { + return true; + } } - if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; - return true; - } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { - if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - buf, buflen, offset, dlinfo.dli_fname)) { - return true; + + // Handle non-dynamic manually: + if (dlinfo.dli_fbase != NULL && + Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, + dlinfo.dli_fbase)) { + if (!Decoder::demangle(localbuf, buf, buflen)) { + jio_snprintf(buf, buflen, "%s", localbuf); + } + return true; } } - - // Handle non-dymanic manually: - if (dlinfo.dli_fbase != NULL && - Decoder::decode(addr, localbuf, MACH_MAXSYMLEN, offset, dlinfo.dli_fbase)) { - if(!Decoder::demangle(localbuf, buf, buflen)) { - jio_snprintf(buf, buflen, "%s", localbuf); - } - return true; - } - if (buf != NULL) buf[0] = '\0'; + buf[0] = '\0'; if (offset != NULL) *offset = -1; return false; } @@ -1287,17 +1293,24 @@ // ported from solaris version bool os::dll_address_to_library_name(address addr, char* buf, int buflen, int* offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + Dl_info dlinfo; - if (dladdr((void*)addr, &dlinfo)){ - if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); - if (offset) *offset = addr - (address)dlinfo.dli_fbase; - return true; - } else { - if (buf) buf[0] = '\0'; - if (offset) *offset = -1; - return false; + if (dladdr((void*)addr, &dlinfo) != 0) { + if (dlinfo.dli_fname != NULL) { + jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); + } + if (dlinfo.dli_fbase != NULL && offset != NULL) { + *offset = addr - (address)dlinfo.dli_fbase; + } + return true; } + + buf[0] = '\0'; + if (offset) *offset = -1; + return false; } // Loads .dll/.so and @@ -1520,49 +1533,50 @@ } void os::print_dll_info(outputStream *st) { - st->print_cr("Dynamic libraries:"); + st->print_cr("Dynamic libraries:"); #ifdef RTLD_DI_LINKMAP - Dl_info dli; - void *handle; - Link_map *map; - Link_map *p; - - if (!dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli)) { - st->print_cr("Error: Cannot print dynamic libraries."); - return; - } - handle = dlopen(dli.dli_fname, RTLD_LAZY); - if (handle == NULL) { - st->print_cr("Error: Cannot print dynamic libraries."); - return; - } - dlinfo(handle, RTLD_DI_LINKMAP, &map); - if (map == NULL) { - st->print_cr("Error: Cannot print dynamic libraries."); - return; - } - - while (map->l_prev != NULL) - map = map->l_prev; - - while (map != NULL) { - st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name); - map = map->l_next; - } - - dlclose(handle); + Dl_info dli; + void *handle; + Link_map *map; + Link_map *p; + + if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 || + dli.dli_fname == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + handle = dlopen(dli.dli_fname, RTLD_LAZY); + if (handle == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + dlinfo(handle, RTLD_DI_LINKMAP, &map); + if (map == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + + while (map->l_prev != NULL) + map = map->l_prev; + + while (map != NULL) { + st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name); + map = map->l_next; + } + + dlclose(handle); #elif defined(__APPLE__) - uint32_t count; - uint32_t i; - - count = _dyld_image_count(); - for (i = 1; i < count; i++) { - const char *name = _dyld_get_image_name(i); - intptr_t slide = _dyld_get_image_vmaddr_slide(i); - st->print_cr(PTR_FORMAT " \t%s", slide, name); - } + uint32_t count; + uint32_t i; + + count = _dyld_image_count(); + for (i = 1; i < count; i++) { + const char *name = _dyld_get_image_name(i); + intptr_t slide = _dyld_get_image_vmaddr_slide(i); + st->print_cr(PTR_FORMAT " \t%s", slide, name); + } #else - st->print_cr("Error: Cannot print dynamic libraries."); + st->print_cr("Error: Cannot print dynamic libraries."); #endif } @@ -1707,8 +1721,11 @@ bool ret = dll_address_to_library_name( CAST_FROM_FN_PTR(address, os::jvm_path), dli_fname, sizeof(dli_fname), NULL); - assert(ret != 0, "cannot locate libjvm"); - char *rp = realpath(dli_fname, buf); + assert(ret, "cannot locate libjvm"); + char *rp = NULL; + if (ret && dli_fname[0] != '\0') { + rp = realpath(dli_fname, buf); + } if (rp == NULL) return; @@ -3747,20 +3764,20 @@ bool os::find(address addr, outputStream* st) { Dl_info dlinfo; memset(&dlinfo, 0, sizeof(dlinfo)); - if (dladdr(addr, &dlinfo)) { + if (dladdr(addr, &dlinfo) != 0) { st->print(PTR_FORMAT ": ", addr); - if (dlinfo.dli_sname != NULL) { + if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) { st->print("%s+%#x", dlinfo.dli_sname, addr - (intptr_t)dlinfo.dli_saddr); - } else if (dlinfo.dli_fname) { + } else if (dlinfo.dli_fbase != NULL) { st->print("", addr - (intptr_t)dlinfo.dli_fbase); } else { st->print(""); } - if (dlinfo.dli_fname) { + if (dlinfo.dli_fname != NULL) { st->print(" in %s", dlinfo.dli_fname); } - if (dlinfo.dli_fbase) { + if (dlinfo.dli_fbase != NULL) { st->print(" at " PTR_FORMAT, dlinfo.dli_fbase); } st->cr(); @@ -3773,7 +3790,7 @@ if (!lowest) lowest = (address) dlinfo.dli_fbase; if (begin < lowest) begin = lowest; Dl_info dlinfo2; - if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr + if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) end = (address) dlinfo2.dli_saddr; Disassembler::decode(begin, end, st); diff -r 1a3390aa8326 -r 2b9946e10587 src/os/linux/vm/os_linux.cpp --- a/src/os/linux/vm/os_linux.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/linux/vm/os_linux.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -1682,12 +1682,13 @@ Dl_info dlinfo; if (libjvm_base_addr == NULL) { - dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo); - libjvm_base_addr = (address)dlinfo.dli_fbase; + if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) { + libjvm_base_addr = (address)dlinfo.dli_fbase; + } assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm"); } - if (dladdr((void *)addr, &dlinfo)) { + if (dladdr((void *)addr, &dlinfo) != 0) { if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true; } @@ -1696,24 +1697,30 @@ bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + Dl_info dlinfo; - if (dladdr((void*)addr, &dlinfo) && dlinfo.dli_sname != NULL) { - if (buf != NULL) { - if(!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { + if (dladdr((void*)addr, &dlinfo) != 0) { + // see if we have a matching symbol + if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) { + if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; + return true; + } + // no matching symbol so try for just file info + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) { + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), + buf, buflen, offset, dlinfo.dli_fname)) { + return true; + } } - if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; - return true; - } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { - if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - buf, buflen, offset, dlinfo.dli_fname)) { - return true; - } - } - - if (buf != NULL) buf[0] = '\0'; + } + + buf[0] = '\0'; if (offset != NULL) *offset = -1; return false; } @@ -1764,6 +1771,9 @@ bool os::dll_address_to_library_name(address addr, char* buf, int buflen, int* offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + Dl_info dlinfo; struct _address_to_library_name data; @@ -1782,15 +1792,20 @@ // buf already contains library name if (offset) *offset = addr - data.base; return true; - } else if (dladdr((void*)addr, &dlinfo)){ - if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); - if (offset) *offset = addr - (address)dlinfo.dli_fbase; - return true; - } else { - if (buf) buf[0] = '\0'; - if (offset) *offset = -1; - return false; - } + } + if (dladdr((void*)addr, &dlinfo) != 0) { + if (dlinfo.dli_fname != NULL) { + jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); + } + if (dlinfo.dli_fbase != NULL && offset != NULL) { + *offset = addr - (address)dlinfo.dli_fbase; + } + return true; + } + + buf[0] = '\0'; + if (offset) *offset = -1; + return false; } // Loads .dll/.so and @@ -2317,8 +2332,11 @@ bool ret = dll_address_to_library_name( CAST_FROM_FN_PTR(address, os::jvm_path), dli_fname, sizeof(dli_fname), NULL); - assert(ret != 0, "cannot locate libjvm"); - char *rp = realpath(dli_fname, buf); + assert(ret, "cannot locate libjvm"); + char *rp = NULL; + if (ret && dli_fname[0] != '\0') { + rp = realpath(dli_fname, buf); + } if (rp == NULL) return; @@ -4730,20 +4748,20 @@ bool os::find(address addr, outputStream* st) { Dl_info dlinfo; memset(&dlinfo, 0, sizeof(dlinfo)); - if (dladdr(addr, &dlinfo)) { + if (dladdr(addr, &dlinfo) != 0) { st->print(PTR_FORMAT ": ", addr); - if (dlinfo.dli_sname != NULL) { + if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) { st->print("%s+%#x", dlinfo.dli_sname, addr - (intptr_t)dlinfo.dli_saddr); - } else if (dlinfo.dli_fname) { + } else if (dlinfo.dli_fbase != NULL) { st->print("", addr - (intptr_t)dlinfo.dli_fbase); } else { st->print(""); } - if (dlinfo.dli_fname) { + if (dlinfo.dli_fname != NULL) { st->print(" in %s", dlinfo.dli_fname); } - if (dlinfo.dli_fbase) { + if (dlinfo.dli_fbase != NULL) { st->print(" at " PTR_FORMAT, dlinfo.dli_fbase); } st->cr(); @@ -4756,7 +4774,7 @@ if (!lowest) lowest = (address) dlinfo.dli_fbase; if (begin < lowest) begin = lowest; Dl_info dlinfo2; - if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr + if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) end = (address) dlinfo2.dli_saddr; Disassembler::decode(begin, end, st); diff -r 1a3390aa8326 -r 2b9946e10587 src/os/solaris/vm/globals_solaris.hpp --- a/src/os/solaris/vm/globals_solaris.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/solaris/vm/globals_solaris.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -30,15 +30,6 @@ // #define RUNTIME_OS_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \ \ - product(bool, UseISM, false, \ - "Use Intimate Shared Memory (Solaris Only)") \ - \ - product(bool, UsePermISM, false, \ - "Obsolete flag for compatibility (same as UseISM)") \ - \ - product(bool, UseMPSS, true, \ - "Use Multiple Page Size Support (Solaris 9 Only)") \ - \ product(bool, UseExtendedFileIO, true, \ "Enable workaround for limitations of stdio FILE structure") diff -r 1a3390aa8326 -r 2b9946e10587 src/os/solaris/vm/os_solaris.cpp --- a/src/os/solaris/vm/os_solaris.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/solaris/vm/os_solaris.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -115,45 +115,6 @@ // for timer info max values which include all bits #define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) -#ifdef _GNU_SOURCE -// See bug #6514594 -extern "C" int madvise(caddr_t, size_t, int); -extern "C" int memcntl(caddr_t addr, size_t len, int cmd, caddr_t arg, - int attr, int mask); -#endif //_GNU_SOURCE - -/* - MPSS Changes Start. - The JVM binary needs to be built and run on pre-Solaris 9 - systems, but the constants needed by MPSS are only in Solaris 9 - header files. They are textually replicated here to allow - building on earlier systems. Once building on Solaris 8 is - no longer a requirement, these #defines can be replaced by ordinary - system .h inclusion. - - In earlier versions of the JDK and Solaris, we used ISM for large pages. - But ISM requires shared memory to achieve this and thus has many caveats. - MPSS is a fully transparent and is a cleaner way to get large pages. - Although we still require keeping ISM for backward compatiblitiy as well as - giving the opportunity to use large pages on older systems it is - recommended that MPSS be used for Solaris 9 and above. - -*/ - -#ifndef MC_HAT_ADVISE - -struct memcntl_mha { - uint_t mha_cmd; /* command(s) */ - uint_t mha_flags; - size_t mha_pagesize; -}; -#define MC_HAT_ADVISE 7 /* advise hat map size */ -#define MHA_MAPSIZE_VA 0x1 /* set preferred page size */ -#define MAP_ALIGN 0x200 /* addr specifies alignment */ - -#endif -// MPSS Changes End. - // Here are some liblgrp types from sys/lgrp_user.h to be able to // compile on older systems without this header file. @@ -172,32 +133,6 @@ # define LGRP_RSRC_MEM 1 /* memory resources */ #endif -// Some more macros from sys/mman.h that are not present in Solaris 8. - -#ifndef MAX_MEMINFO_CNT -/* - * info_req request type definitions for meminfo - * request types starting with MEMINFO_V are used for Virtual addresses - * and should not be mixed with MEMINFO_PLGRP which is targeted for Physical - * addresses - */ -# define MEMINFO_SHIFT 16 -# define MEMINFO_MASK (0xFF << MEMINFO_SHIFT) -# define MEMINFO_VPHYSICAL (0x01 << MEMINFO_SHIFT) /* get physical addr */ -# define MEMINFO_VLGRP (0x02 << MEMINFO_SHIFT) /* get lgroup */ -# define MEMINFO_VPAGESIZE (0x03 << MEMINFO_SHIFT) /* size of phys page */ -# define MEMINFO_VREPLCNT (0x04 << MEMINFO_SHIFT) /* no. of replica */ -# define MEMINFO_VREPL (0x05 << MEMINFO_SHIFT) /* physical replica */ -# define MEMINFO_VREPL_LGRP (0x06 << MEMINFO_SHIFT) /* lgrp of replica */ -# define MEMINFO_PLGRP (0x07 << MEMINFO_SHIFT) /* lgroup for paddr */ - -/* maximum number of addresses meminfo() can process at a time */ -# define MAX_MEMINFO_CNT 256 - -/* maximum number of request types */ -# define MAX_MEMINFO_REQ 31 -#endif - // see thr_setprio(3T) for the basis of these numbers #define MinimumPriority 0 #define NormalPriority 64 @@ -1924,12 +1859,13 @@ Dl_info dlinfo; if (libjvm_base_addr == NULL) { - dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo); - libjvm_base_addr = (address)dlinfo.dli_fbase; + if (dladdr(CAST_FROM_FN_PTR(void *, os::address_is_in_vm), &dlinfo) != 0) { + libjvm_base_addr = (address)dlinfo.dli_fbase; + } assert(libjvm_base_addr !=NULL, "Cannot obtain base address for libjvm"); } - if (dladdr((void *)addr, &dlinfo)) { + if (dladdr((void *)addr, &dlinfo) != 0) { if (libjvm_base_addr == (address)dlinfo.dli_fbase) return true; } @@ -1941,114 +1877,133 @@ bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int * offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + Dl_info dlinfo; // dladdr1_func was initialized in os::init() - if (dladdr1_func){ - // yes, we have dladdr1 - - // Support for dladdr1 is checked at runtime; it may be - // available even if the vm is built on a machine that does - // not have dladdr1 support. Make sure there is a value for - // RTLD_DL_SYMENT. - #ifndef RTLD_DL_SYMENT - #define RTLD_DL_SYMENT 1 - #endif + if (dladdr1_func != NULL) { + // yes, we have dladdr1 + + // Support for dladdr1 is checked at runtime; it may be + // available even if the vm is built on a machine that does + // not have dladdr1 support. Make sure there is a value for + // RTLD_DL_SYMENT. + #ifndef RTLD_DL_SYMENT + #define RTLD_DL_SYMENT 1 + #endif #ifdef _LP64 - Elf64_Sym * info; + Elf64_Sym * info; #else - Elf32_Sym * info; + Elf32_Sym * info; #endif - if (dladdr1_func((void *)addr, &dlinfo, (void **)&info, - RTLD_DL_SYMENT)) { - if ((char *)dlinfo.dli_saddr + info->st_size > (char *)addr) { - if (buf != NULL) { - if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) - jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); - } - if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; - return true; - } - } - if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { - if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - buf, buflen, offset, dlinfo.dli_fname)) { + if (dladdr1_func((void *)addr, &dlinfo, (void **)&info, + RTLD_DL_SYMENT) != 0) { + // see if we have a matching symbol that covers our address + if (dlinfo.dli_saddr != NULL && + (char *)dlinfo.dli_saddr + info->st_size > (char *)addr) { + if (dlinfo.dli_sname != NULL) { + if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { + jio_snprintf(buf, buflen, "%s", dlinfo.dli_sname); + } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; return true; } } - if (buf != NULL) buf[0] = '\0'; - if (offset != NULL) *offset = -1; - return false; - } else { - // no, only dladdr is available - if (dladdr((void *)addr, &dlinfo)) { - if (buf != NULL) { - if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) - jio_snprintf(buf, buflen, dlinfo.dli_sname); - } - if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; - return true; - } else if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != 0) { + // no matching symbol so try for just file info + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) { if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), - buf, buflen, offset, dlinfo.dli_fname)) { + buf, buflen, offset, dlinfo.dli_fname)) { return true; } } - if (buf != NULL) buf[0] = '\0'; - if (offset != NULL) *offset = -1; - return false; - } + } + buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; + } + + // no, only dladdr is available + if (dladdr((void *)addr, &dlinfo) != 0) { + // see if we have a matching symbol + if (dlinfo.dli_saddr != NULL && dlinfo.dli_sname != NULL) { + if (!Decoder::demangle(dlinfo.dli_sname, buf, buflen)) { + jio_snprintf(buf, buflen, dlinfo.dli_sname); + } + if (offset != NULL) *offset = addr - (address)dlinfo.dli_saddr; + return true; + } + // no matching symbol so try for just file info + if (dlinfo.dli_fname != NULL && dlinfo.dli_fbase != NULL) { + if (Decoder::decode((address)(addr - (address)dlinfo.dli_fbase), + buf, buflen, offset, dlinfo.dli_fname)) { + return true; + } + } + } + buf[0] = '\0'; + if (offset != NULL) *offset = -1; + return false; } bool os::dll_address_to_library_name(address addr, char* buf, int buflen, int* offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + Dl_info dlinfo; - if (dladdr((void*)addr, &dlinfo)){ - if (buf) jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); - if (offset) *offset = addr - (address)dlinfo.dli_fbase; - return true; - } else { - if (buf) buf[0] = '\0'; - if (offset) *offset = -1; - return false; - } + if (dladdr((void*)addr, &dlinfo) != 0) { + if (dlinfo.dli_fname != NULL) { + jio_snprintf(buf, buflen, "%s", dlinfo.dli_fname); + } + if (dlinfo.dli_fbase != NULL && offset != NULL) { + *offset = addr - (address)dlinfo.dli_fbase; + } + return true; + } + + buf[0] = '\0'; + if (offset) *offset = -1; + return false; } // Prints the names and full paths of all opened dynamic libraries // for current process void os::print_dll_info(outputStream * st) { - Dl_info dli; - void *handle; - Link_map *map; - Link_map *p; - - st->print_cr("Dynamic libraries:"); st->flush(); - - if (!dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli)) { - st->print_cr("Error: Cannot print dynamic libraries."); - return; - } - handle = dlopen(dli.dli_fname, RTLD_LAZY); - if (handle == NULL) { - st->print_cr("Error: Cannot print dynamic libraries."); - return; - } - dlinfo(handle, RTLD_DI_LINKMAP, &map); - if (map == NULL) { - st->print_cr("Error: Cannot print dynamic libraries."); - return; - } - - while (map->l_prev != NULL) - map = map->l_prev; - - while (map != NULL) { - st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name); - map = map->l_next; - } - - dlclose(handle); + Dl_info dli; + void *handle; + Link_map *map; + Link_map *p; + + st->print_cr("Dynamic libraries:"); st->flush(); + + if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 || + dli.dli_fname == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + handle = dlopen(dli.dli_fname, RTLD_LAZY); + if (handle == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + dlinfo(handle, RTLD_DI_LINKMAP, &map); + if (map == NULL) { + st->print_cr("Error: Cannot print dynamic libraries."); + return; + } + + while (map->l_prev != NULL) + map = map->l_prev; + + while (map != NULL) { + st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name); + map = map->l_next; + } + + dlclose(handle); } // Loads .dll/.so and @@ -2475,7 +2430,12 @@ Dl_info dlinfo; int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo); assert(ret != 0, "cannot locate libjvm"); - realpath((char *)dlinfo.dli_fname, buf); + if (ret != 0 && dlinfo.dli_fname != NULL) { + realpath((char *)dlinfo.dli_fname, buf); + } else { + buf[0] = '\0'; + return; + } if (Arguments::created_by_gamma_launcher()) { // Support for the gamma launcher. Typical value for buf is @@ -2859,7 +2819,7 @@ size_t alignment_hint, bool exec) { int err = Solaris::commit_memory_impl(addr, bytes, exec); if (err == 0) { - if (UseMPSS && alignment_hint > (size_t)vm_page_size()) { + if (UseLargePages && (alignment_hint > (size_t)vm_page_size())) { // If the large page size has been set and the VM // is using large pages, use the large page size // if it is smaller than the alignment hint. This is @@ -2878,7 +2838,7 @@ page_size = alignment_hint; } // Since this is a hint, ignore any failures. - (void)Solaris::set_mpss_range(addr, bytes, page_size); + (void)Solaris::setup_large_pages(addr, bytes, page_size); } } return err; @@ -2921,8 +2881,8 @@ void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { assert((intptr_t)addr % alignment_hint == 0, "Address should be aligned."); assert((intptr_t)(addr + bytes) % alignment_hint == 0, "End should be aligned."); - if (UseLargePages && UseMPSS) { - Solaris::set_mpss_range(addr, bytes, alignment_hint); + if (UseLargePages) { + Solaris::setup_large_pages(addr, bytes, alignment_hint); } } @@ -3321,47 +3281,8 @@ } // Large page support - -// UseLargePages is the master flag to enable/disable large page memory. -// UseMPSS and UseISM are supported for compatibility reasons. Their combined -// effects can be described in the following table: -// -// UseLargePages UseMPSS UseISM -// false * * => UseLargePages is the master switch, turning -// it off will turn off both UseMPSS and -// UseISM. VM will not use large page memory -// regardless the settings of UseMPSS/UseISM. -// true false false => Unless future Solaris provides other -// mechanism to use large page memory, this -// combination is equivalent to -UseLargePages, -// VM will not use large page memory -// true true false => JVM will use MPSS for large page memory. -// This is the default behavior. -// true false true => JVM will use ISM for large page memory. -// true true true => JVM will use ISM if it is available. -// Otherwise, JVM will fall back to MPSS. -// Becaues ISM is now available on all -// supported Solaris versions, this combination -// is equivalent to +UseISM -UseMPSS. - static size_t _large_page_size = 0; -bool os::Solaris::ism_sanity_check(bool warn, size_t * page_size) { - // x86 uses either 2M or 4M page, depending on whether PAE (Physical Address - // Extensions) mode is enabled. AMD64/EM64T uses 2M page in 64bit mode. Sparc - // can support multiple page sizes. - - // Don't bother to probe page size because getpagesizes() comes with MPSS. - // ISM is only recommended on old Solaris where there is no MPSS support. - // Simply choose a conservative value as default. - *page_size = LargePageSizeInBytes ? LargePageSizeInBytes : - SPARC_ONLY(4 * M) IA32_ONLY(4 * M) AMD64_ONLY(2 * M) - ARM_ONLY(2 * M); - - // ISM is available on all supported Solaris versions - return true; -} - // Insertion sort for small arrays (descending order). static void insertion_sort_descending(size_t* array, int len) { for (int i = 0; i < len; i++) { @@ -3374,7 +3295,7 @@ } } -bool os::Solaris::mpss_sanity_check(bool warn, size_t * page_size) { +bool os::Solaris::mpss_sanity_check(bool warn, size_t* page_size) { const unsigned int usable_count = VM_Version::page_size_count(); if (usable_count == 1) { return false; @@ -3440,41 +3361,24 @@ } void os::large_page_init() { - if (!UseLargePages) { - UseISM = false; - UseMPSS = false; - return; - } - - // print a warning if any large page related flag is specified on command line - bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) || - !FLAG_IS_DEFAULT(UseISM) || - !FLAG_IS_DEFAULT(UseMPSS) || - !FLAG_IS_DEFAULT(LargePageSizeInBytes); - UseISM = UseISM && - Solaris::ism_sanity_check(warn_on_failure, &_large_page_size); - if (UseISM) { - // ISM disables MPSS to be compatible with old JDK behavior - UseMPSS = false; - _page_sizes[0] = _large_page_size; - _page_sizes[1] = vm_page_size(); - } - - UseMPSS = UseMPSS && - Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size); - - UseLargePages = UseISM || UseMPSS; -} - -bool os::Solaris::set_mpss_range(caddr_t start, size_t bytes, size_t align) { + if (UseLargePages) { + // print a warning if any large page related flag is specified on command line + bool warn_on_failure = !FLAG_IS_DEFAULT(UseLargePages) || + !FLAG_IS_DEFAULT(LargePageSizeInBytes); + + UseLargePages = Solaris::mpss_sanity_check(warn_on_failure, &_large_page_size); + } +} + +bool os::Solaris::setup_large_pages(caddr_t start, size_t bytes, size_t align) { // Signal to OS that we want large pages for addresses // from addr, addr + bytes struct memcntl_mha mpss_struct; mpss_struct.mha_cmd = MHA_MAPSIZE_VA; mpss_struct.mha_pagesize = align; mpss_struct.mha_flags = 0; - if (memcntl(start, bytes, MC_HAT_ADVISE, - (caddr_t) &mpss_struct, 0, 0) < 0) { + // Upon successful completion, memcntl() returns 0 + if (memcntl(start, bytes, MC_HAT_ADVISE, (caddr_t) &mpss_struct, 0, 0)) { debug_only(warning("Attempt to use MPSS failed.")); return false; } @@ -3482,72 +3386,13 @@ } char* os::reserve_memory_special(size_t size, char* addr, bool exec) { - // "exec" is passed in but not used. Creating the shared image for - // the code cache doesn't have an SHM_X executable permission to check. - assert(UseLargePages && UseISM, "only for ISM large pages"); - - char* retAddr = NULL; - int shmid; - key_t ismKey; - - bool warn_on_failure = UseISM && - (!FLAG_IS_DEFAULT(UseLargePages) || - !FLAG_IS_DEFAULT(UseISM) || - !FLAG_IS_DEFAULT(LargePageSizeInBytes) - ); - char msg[128]; - - ismKey = IPC_PRIVATE; - - // Create a large shared memory region to attach to based on size. - // Currently, size is the total size of the heap - shmid = shmget(ismKey, size, SHM_R | SHM_W | IPC_CREAT); - if (shmid == -1){ - if (warn_on_failure) { - jio_snprintf(msg, sizeof(msg), "Failed to reserve shared memory (errno = %d).", errno); - warning(msg); - } - return NULL; - } - - // Attach to the region - retAddr = (char *) shmat(shmid, 0, SHM_SHARE_MMU | SHM_R | SHM_W); - int err = errno; - - // Remove shmid. If shmat() is successful, the actual shared memory segment - // will be deleted when it's detached by shmdt() or when the process - // terminates. If shmat() is not successful this will remove the shared - // segment immediately. - shmctl(shmid, IPC_RMID, NULL); - - if (retAddr == (char *) -1) { - if (warn_on_failure) { - jio_snprintf(msg, sizeof(msg), "Failed to attach shared memory (errno = %d).", err); - warning(msg); - } - return NULL; - } - if ((retAddr != NULL) && UseNUMAInterleaving) { - numa_make_global(retAddr, size); - } - - // The memory is committed - MemTracker::record_virtual_memory_reserve_and_commit((address)retAddr, size, mtNone, CURRENT_PC); - - return retAddr; + fatal("os::reserve_memory_special should not be called on Solaris."); + return NULL; } bool os::release_memory_special(char* base, size_t bytes) { - MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker(); - // detaching the SHM segment will also delete it, see reserve_memory_special() - int rslt = shmdt(base); - if (rslt == 0) { - tkr.record((address)base, bytes); - return true; - } else { - tkr.discard(); - return false; - } + fatal("os::release_memory_special should not be called on Solaris."); + return false; } size_t os::large_page_size() { @@ -3557,11 +3402,11 @@ // MPSS allows application to commit large page memory on demand; with ISM // the entire memory region must be allocated as shared memory. bool os::can_commit_large_page_memory() { - return UseISM ? false : true; + return true; } bool os::can_execute_large_page_memory() { - return UseISM ? false : true; + return true; } static int os_sleep(jlong millis, bool interruptible) { @@ -3835,28 +3680,6 @@ static const int criticalPrio = 60; // FX/60 is critical thread class/priority on T4 static int java_MaxPriority_to_os_priority = 0; // Saved mapping -// Call the version of priocntl suitable for all supported versions -// of Solaris. We need to call through this wrapper so that we can -// build on Solaris 9 and run on Solaris 8, 9 and 10. -// -// This code should be removed if we ever stop supporting Solaris 8 -// and earlier releases. - -static long priocntl_stub(int pcver, idtype_t idtype, id_t id, int cmd, caddr_t arg); -typedef long (*priocntl_type)(int pcver, idtype_t idtype, id_t id, int cmd, caddr_t arg); -static priocntl_type priocntl_ptr = priocntl_stub; - -// Stub to set the value of the real pointer, and then call the real -// function. - -static long priocntl_stub(int pcver, idtype_t idtype, id_t id, int cmd, caddr_t arg) { - // Try Solaris 8- name only. - priocntl_type tmp = (priocntl_type)dlsym(RTLD_DEFAULT, "__priocntl"); - guarantee(tmp != NULL, "priocntl function not found."); - priocntl_ptr = tmp; - return (*priocntl_ptr)(PC_VERSION, idtype, id, cmd, arg); -} - // lwp_priocntl_init // @@ -3864,9 +3687,7 @@ // // Return errno or 0 if OK. // -static -int lwp_priocntl_init () -{ +static int lwp_priocntl_init () { int rslt; pcinfo_t ClassInfo; pcparms_t ParmInfo; @@ -3906,7 +3727,7 @@ strcpy(ClassInfo.pc_clname, "TS"); ClassInfo.pc_cid = -1; - rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); if (rslt < 0) return errno; assert(ClassInfo.pc_cid != -1, "cid for TS class is -1"); tsLimits.schedPolicy = ClassInfo.pc_cid; @@ -3915,7 +3736,7 @@ strcpy(ClassInfo.pc_clname, "IA"); ClassInfo.pc_cid = -1; - rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); if (rslt < 0) return errno; assert(ClassInfo.pc_cid != -1, "cid for IA class is -1"); iaLimits.schedPolicy = ClassInfo.pc_cid; @@ -3924,7 +3745,7 @@ strcpy(ClassInfo.pc_clname, "RT"); ClassInfo.pc_cid = -1; - rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); if (rslt < 0) return errno; assert(ClassInfo.pc_cid != -1, "cid for RT class is -1"); rtLimits.schedPolicy = ClassInfo.pc_cid; @@ -3933,7 +3754,7 @@ strcpy(ClassInfo.pc_clname, "FX"); ClassInfo.pc_cid = -1; - rslt = (*priocntl_ptr)(PC_VERSION, P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); + rslt = priocntl(P_ALL, 0, PC_GETCID, (caddr_t)&ClassInfo); if (rslt < 0) return errno; assert(ClassInfo.pc_cid != -1, "cid for FX class is -1"); fxLimits.schedPolicy = ClassInfo.pc_cid; @@ -3944,7 +3765,7 @@ // This will normally be IA, TS or, rarely, FX or RT. memset(&ParmInfo, 0, sizeof(ParmInfo)); ParmInfo.pc_cid = PC_CLNULL; - rslt = (*priocntl_ptr) (PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo); + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo); if (rslt < 0) return errno; myClass = ParmInfo.pc_cid; @@ -3952,7 +3773,7 @@ // about the class. ClassInfo.pc_cid = myClass; ClassInfo.pc_clname[0] = 0; - rslt = (*priocntl_ptr) (PC_VERSION, (idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo); + rslt = priocntl((idtype)0, 0, PC_GETCLINFO, (caddr_t)&ClassInfo); if (rslt < 0) return errno; if (ThreadPriorityVerbose) { @@ -3961,7 +3782,7 @@ memset(&ParmInfo, 0, sizeof(pcparms_t)); ParmInfo.pc_cid = PC_CLNULL; - rslt = (*priocntl_ptr)(PC_VERSION, P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo); + rslt = priocntl(P_PID, P_MYID, PC_GETPARMS, (caddr_t)&ParmInfo); if (rslt < 0) return errno; if (ParmInfo.pc_cid == rtLimits.schedPolicy) { @@ -4065,7 +3886,7 @@ memset(&ParmInfo, 0, sizeof(pcparms_t)); ParmInfo.pc_cid = PC_CLNULL; - rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo); + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ParmInfo); if (rslt < 0) return errno; int cur_class = ParmInfo.pc_cid; @@ -4133,7 +3954,7 @@ return EINVAL; // no clue, punt } - rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo); + rslt = priocntl(P_LWPID, lwpid, PC_SETPARMS, (caddr_t)&ParmInfo); if (ThreadPriorityVerbose && rslt) { tty->print_cr ("PC_SETPARMS ->%d %d\n", rslt, errno); } @@ -4152,7 +3973,7 @@ memset(&ReadBack, 0, sizeof(pcparms_t)); ReadBack.pc_cid = PC_CLNULL; - rslt = (*priocntl_ptr)(PC_VERSION, P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ReadBack); + rslt = priocntl(P_LWPID, lwpid, PC_GETPARMS, (caddr_t)&ReadBack); assert(rslt >= 0, "priocntl failed"); Actual = Expected = 0xBAD; assert(ParmInfo.pc_cid == ReadBack.pc_cid, "cid's don't match"); @@ -5244,11 +5065,6 @@ return _getisax(array, n); } -// Symbol doesn't exist in Solaris 8 pset.h -#ifndef PS_MYID -#define PS_MYID -3 -#endif - // int pset_getloadavg(psetid_t pset, double loadavg[], int nelem); typedef long (*pset_getloadavg_type)(psetid_t pset, double loadavg[], int nelem); static pset_getloadavg_type pset_getloadavg_ptr = NULL; @@ -5418,20 +5234,6 @@ UseNUMA = false; } } - // ISM is not compatible with the NUMA allocator - it always allocates - // pages round-robin across the lgroups. - if (UseNUMA && UseLargePages && UseISM) { - if (!FLAG_IS_DEFAULT(UseNUMA)) { - if (FLAG_IS_DEFAULT(UseLargePages) && FLAG_IS_DEFAULT(UseISM)) { - UseLargePages = false; - } else { - warning("UseNUMA is not compatible with ISM large pages, disabling NUMA allocator"); - UseNUMA = false; - } - } else { - UseNUMA = false; - } - } if (!UseNUMA && ForceNUMA) { UseNUMA = true; } @@ -6077,24 +5879,20 @@ bool os::find(address addr, outputStream* st) { Dl_info dlinfo; memset(&dlinfo, 0, sizeof(dlinfo)); - if (dladdr(addr, &dlinfo)) { -#ifdef _LP64 - st->print("0x%016lx: ", addr); -#else - st->print("0x%08x: ", addr); -#endif - if (dlinfo.dli_sname != NULL) + if (dladdr(addr, &dlinfo) != 0) { + st->print(PTR_FORMAT ": ", addr); + if (dlinfo.dli_sname != NULL && dlinfo.dli_saddr != NULL) { st->print("%s+%#lx", dlinfo.dli_sname, addr-(intptr_t)dlinfo.dli_saddr); - else if (dlinfo.dli_fname) + } else if (dlinfo.dli_fbase != NULL) st->print("", addr-(intptr_t)dlinfo.dli_fbase); else st->print(""); - if (dlinfo.dli_fname) st->print(" in %s", dlinfo.dli_fname); -#ifdef _LP64 - if (dlinfo.dli_fbase) st->print(" at 0x%016lx", dlinfo.dli_fbase); -#else - if (dlinfo.dli_fbase) st->print(" at 0x%08x", dlinfo.dli_fbase); -#endif + if (dlinfo.dli_fname != NULL) { + st->print(" in %s", dlinfo.dli_fname); + } + if (dlinfo.dli_fbase != NULL) { + st->print(" at " PTR_FORMAT, dlinfo.dli_fbase); + } st->cr(); if (Verbose) { @@ -6105,7 +5903,7 @@ if (!lowest) lowest = (address) dlinfo.dli_fbase; if (begin < lowest) begin = lowest; Dl_info dlinfo2; - if (dladdr(end, &dlinfo2) && dlinfo2.dli_saddr != dlinfo.dli_saddr + if (dladdr(end, &dlinfo2) != 0 && dlinfo2.dli_saddr != dlinfo.dli_saddr && end > dlinfo2.dli_saddr && dlinfo2.dli_saddr > begin) end = (address) dlinfo2.dli_saddr; Disassembler::decode(begin, end, st); diff -r 1a3390aa8326 -r 2b9946e10587 src/os/solaris/vm/os_solaris.hpp --- a/src/os/solaris/vm/os_solaris.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/solaris/vm/os_solaris.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -106,8 +106,8 @@ static meminfo_func_t _meminfo; - // Large Page Support--mpss. - static bool set_mpss_range(caddr_t start, size_t bytes, size_t align); + // Large Page Support + static bool setup_large_pages(caddr_t start, size_t bytes, size_t align); static void init_thread_fpu_state(void); @@ -174,7 +174,6 @@ static char* mmap_chunk(char *addr, size_t size, int flags, int prot); static char* anon_mmap(char* requested_addr, size_t bytes, size_t alignment_hint, bool fixed); static bool mpss_sanity_check(bool warn, size_t * page_size); - static bool ism_sanity_check (bool warn, size_t * page_size); // Workaround for 4352906. thr_stksegment sometimes returns // a bad value for the primordial thread's stack base when diff -r 1a3390aa8326 -r 2b9946e10587 src/os/windows/vm/os_windows.cpp --- a/src/os/windows/vm/os_windows.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/windows/vm/os_windows.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -1420,34 +1420,40 @@ bool os::dll_address_to_library_name(address addr, char* buf, int buflen, int* offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + // NOTE: the reason we don't use SymGetModuleInfo() is it doesn't always // return the full path to the DLL file, sometimes it returns path // to the corresponding PDB file (debug info); sometimes it only // returns partial path, which makes life painful. - struct _modinfo mi; - mi.addr = addr; - mi.full_path = buf; - mi.buflen = buflen; - int pid = os::current_process_id(); - if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) { - // buf already contains path name - if (offset) *offset = addr - mi.base_addr; - return true; - } else { - if (buf) buf[0] = '\0'; - if (offset) *offset = -1; - return false; - } + struct _modinfo mi; + mi.addr = addr; + mi.full_path = buf; + mi.buflen = buflen; + int pid = os::current_process_id(); + if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) { + // buf already contains path name + if (offset) *offset = addr - mi.base_addr; + return true; + } + + buf[0] = '\0'; + if (offset) *offset = -1; + return false; } bool os::dll_address_to_function_name(address addr, char *buf, int buflen, int *offset) { + // buf is not optional, but offset is optional + assert(buf != NULL, "sanity check"); + if (Decoder::decode(addr, buf, buflen, offset)) { return true; } if (offset != NULL) *offset = -1; - if (buf != NULL) buf[0] = '\0'; + buf[0] = '\0'; return false; } @@ -2689,6 +2695,19 @@ } #endif +#ifndef PRODUCT +void os::win32::call_test_func_with_wrapper(void (*funcPtr)(void)) { + // Install a win32 structured exception handler around the test + // function call so the VM can generate an error dump if needed. + __try { + (*funcPtr)(); + } __except(topLevelExceptionFilter( + (_EXCEPTION_POINTERS*)_exception_info())) { + // Nothing to do. + } +} +#endif + // Virtual Memory int os::vm_page_size() { return os::win32::vm_page_size(); } diff -r 1a3390aa8326 -r 2b9946e10587 src/os/windows/vm/os_windows.hpp --- a/src/os/windows/vm/os_windows.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/windows/vm/os_windows.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -94,6 +94,10 @@ static address fast_jni_accessor_wrapper(BasicType); #endif +#ifndef PRODUCT + static void call_test_func_with_wrapper(void (*funcPtr)(void)); +#endif + // filter function to ignore faults on serializations page static LONG WINAPI serialize_fault_filter(struct _EXCEPTION_POINTERS* e); }; diff -r 1a3390aa8326 -r 2b9946e10587 src/os/windows/vm/os_windows.inline.hpp --- a/src/os/windows/vm/os_windows.inline.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/os/windows/vm/os_windows.inline.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -106,4 +106,10 @@ inline int os::close(int fd) { return ::close(fd); } + +#ifndef PRODUCT + #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) \ + os::win32::call_test_func_with_wrapper(f) +#endif + #endif // OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/adlc/forms.hpp --- a/src/share/vm/adlc/forms.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/adlc/forms.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,7 +146,7 @@ // Public Methods Form(int formType=0, int line=0) : _next(NULL), _linenum(line), _ftype(formType) { }; - ~Form() {}; + virtual ~Form() {}; virtual bool ideal_only() const { assert(0,"Check of ideal status on non-instruction/operand form.\n"); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/classfile/defaultMethods.cpp --- a/src/share/vm/classfile/defaultMethods.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/classfile/defaultMethods.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -318,17 +318,17 @@ } }; + // A method family contains a set of all methods that implement a single -// language-level method. Because of erasure, these methods may have different -// signatures. As members of the set are collected while walking over the +// erased method. As members of the set are collected while walking over the // hierarchy, they are tagged with a qualification state. The qualification // state for an erased method is set to disqualified if there exists a path // from the root of hierarchy to the method that contains an interleaving -// language-equivalent method defined in an interface. +// erased method defined in an interface. + class MethodFamily : public ResourceObj { private: - generic::MethodDescriptor* _descriptor; // language-level description GrowableArray > _members; ResourceHashtable _member_index; @@ -358,15 +358,8 @@ public: - MethodFamily(generic::MethodDescriptor* canonical_desc) - : _descriptor(canonical_desc), _selected_target(NULL), - _exception_message(NULL) {} - - generic::MethodDescriptor* descriptor() const { return _descriptor; } - - bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) { - return descriptor()->covariant_match(md, ctx); - } + MethodFamily() + : _selected_target(NULL), _exception_message(NULL) {} void set_target_if_empty(Method* m) { if (_selected_target == NULL && !m->is_overpass()) { @@ -441,16 +434,10 @@ } #ifndef PRODUCT - void print_on(outputStream* str) const { - print_on(str, 0); - } - - void print_on(outputStream* str, int indent) const { + void print_sig_on(outputStream* str, Symbol* signature, int indent) const { streamIndentor si(str, indent * 2); - generic::Context ctx(NULL); // empty, as _descriptor already canonicalized - TempNewSymbol family = descriptor()->reify_signature(&ctx, Thread::current()); - str->indent().print_cr("Logical Method %s:", family->as_C_string()); + str->indent().print_cr("Logical Method %s:", signature->as_C_string()); streamIndentor si2(str); for (int i = 0; i < _members.length(); ++i) { @@ -516,36 +503,92 @@ return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL); } +// A generic method family contains a set of all methods that implement a single +// language-level method. Because of erasure, these methods may have different +// signatures. As members of the set are collected while walking over the +// hierarchy, they are tagged with a qualification state. The qualification +// state for an erased method is set to disqualified if there exists a path +// from the root of hierarchy to the method that contains an interleaving +// language-equivalent method defined in an interface. +class GenericMethodFamily : public MethodFamily { + private: + + generic::MethodDescriptor* _descriptor; // language-level description + + public: + + GenericMethodFamily(generic::MethodDescriptor* canonical_desc) + : _descriptor(canonical_desc) {} + + generic::MethodDescriptor* descriptor() const { return _descriptor; } + + bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) { + return descriptor()->covariant_match(md, ctx); + } + +#ifndef PRODUCT + Symbol* get_generic_sig() const { + + generic::Context ctx(NULL); // empty, as _descriptor already canonicalized + TempNewSymbol sig = descriptor()->reify_signature(&ctx, Thread::current()); + return sig; + } +#endif // ndef PRODUCT +}; + class StateRestorer; -// StatefulMethodFamily is a wrapper around MethodFamily that maintains the +// StatefulMethodFamily is a wrapper around a MethodFamily that maintains the // qualification state during hierarchy visitation, and applies that state -// when adding members to the MethodFamily. +// when adding members to the MethodFamily class StatefulMethodFamily : public ResourceObj { friend class StateRestorer; private: - MethodFamily* _method; QualifiedState _qualification_state; void set_qualification_state(QualifiedState state) { _qualification_state = state; } + protected: + MethodFamily* _method_family; + public: - StatefulMethodFamily(generic::MethodDescriptor* md, generic::Context* ctx) { - _method = new MethodFamily(md->canonicalize(ctx)); - _qualification_state = QUALIFIED; + StatefulMethodFamily() { + _method_family = new MethodFamily(); + _qualification_state = QUALIFIED; + } + + StatefulMethodFamily(MethodFamily* mf) { + _method_family = mf; + _qualification_state = QUALIFIED; } - void set_target_if_empty(Method* m) { _method->set_target_if_empty(m); } + void set_target_if_empty(Method* m) { _method_family->set_target_if_empty(m); } + + MethodFamily* get_method_family() { return _method_family; } + + StateRestorer* record_method_and_dq_further(Method* mo); +}; + - MethodFamily* get_method_family() { return _method; } +// StatefulGenericMethodFamily is a wrapper around GenericMethodFamily that maintains the +// qualification state during hierarchy visitation, and applies that state +// when adding members to the GenericMethodFamily. +class StatefulGenericMethodFamily : public StatefulMethodFamily { + + public: + StatefulGenericMethodFamily(generic::MethodDescriptor* md, generic::Context* ctx) + : StatefulMethodFamily(new GenericMethodFamily(md->canonicalize(ctx))) { + + } + GenericMethodFamily* get_method_family() { + return (GenericMethodFamily*)_method_family; + } bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) { - return _method->descriptor_matches(md, ctx); + return get_method_family()->descriptor_matches(md, ctx); } - - StateRestorer* record_method_and_dq_further(Method* mo); }; class StateRestorer : public PseudoScopeMark { @@ -563,9 +606,9 @@ StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) { StateRestorer* mark = new StateRestorer(this, _qualification_state); if (_qualification_state == QUALIFIED) { - _method->record_qualified_method(mo); + _method_family->record_qualified_method(mo); } else { - _method->record_disqualified_method(mo); + _method_family->record_disqualified_method(mo); } // Everything found "above"??? this method in the hierarchy walk is set to // disqualified @@ -573,15 +616,15 @@ return mark; } -class StatefulMethodFamilies : public ResourceObj { +class StatefulGenericMethodFamilies : public ResourceObj { private: - GrowableArray _methods; + GrowableArray _methods; public: - StatefulMethodFamily* find_matching( + StatefulGenericMethodFamily* find_matching( generic::MethodDescriptor* md, generic::Context* ctx) { for (int i = 0; i < _methods.length(); ++i) { - StatefulMethodFamily* existing = _methods.at(i); + StatefulGenericMethodFamily* existing = _methods.at(i); if (existing->descriptor_matches(md, ctx)) { return existing; } @@ -589,17 +632,17 @@ return NULL; } - StatefulMethodFamily* find_matching_or_create( + StatefulGenericMethodFamily* find_matching_or_create( generic::MethodDescriptor* md, generic::Context* ctx) { - StatefulMethodFamily* method = find_matching(md, ctx); + StatefulGenericMethodFamily* method = find_matching(md, ctx); if (method == NULL) { - method = new StatefulMethodFamily(md, ctx); + method = new StatefulGenericMethodFamily(md, ctx); _methods.append(method); } return method; } - void extract_families_into(GrowableArray* array) { + void extract_families_into(GrowableArray* array) { for (int i = 0; i < _methods.length(); ++i) { array->append(_methods.at(i)->get_method_family()); } @@ -683,26 +726,79 @@ return slots; } +// Iterates over the superinterface type hierarchy looking for all methods +// with a specific erased signature. +class FindMethodsByErasedSig : public HierarchyVisitor { + private: + // Context data + Symbol* _method_name; + Symbol* _method_signature; + StatefulMethodFamily* _family; + + public: + FindMethodsByErasedSig(Symbol* name, Symbol* signature) : + _method_name(name), _method_signature(signature), + _family(NULL) {} + + void get_discovered_family(MethodFamily** family) { + if (_family != NULL) { + *family = _family->get_method_family(); + } else { + *family = NULL; + } + } + + void* new_node_data(InstanceKlass* cls) { return new PseudoScope(); } + void free_node_data(void* node_data) { + PseudoScope::cast(node_data)->destroy(); + } + + // Find all methods on this hierarchy that match this + // method's erased (name, signature) + bool visit() { + PseudoScope* scope = PseudoScope::cast(current_data()); + InstanceKlass* iklass = current_class(); + + Method* m = iklass->find_method(_method_name, _method_signature); + if (m != NULL) { + if (_family == NULL) { + _family = new StatefulMethodFamily(); + } + + if (iklass->is_interface()) { + StateRestorer* restorer = _family->record_method_and_dq_further(m); + scope->add_mark(restorer); + } else { + // This is the rule that methods in classes "win" (bad word) over + // methods in interfaces. This works because of single inheritance + _family->set_target_if_empty(m); + } + } + return true; + } + +}; + // Iterates over the type hierarchy looking for all methods with a specific // method name. The result of this is a set of method families each of // which is populated with a set of methods that implement the same // language-level signature. -class FindMethodsByName : public HierarchyVisitor { +class FindMethodsByGenericSig : public HierarchyVisitor { private: // Context data Thread* THREAD; generic::DescriptorCache* _cache; Symbol* _method_name; generic::Context* _ctx; - StatefulMethodFamilies _families; + StatefulGenericMethodFamilies _families; public: - FindMethodsByName(generic::DescriptorCache* cache, Symbol* name, + FindMethodsByGenericSig(generic::DescriptorCache* cache, Symbol* name, generic::Context* ctx, Thread* thread) : _cache(cache), _method_name(name), _ctx(ctx), THREAD(thread) {} - void get_discovered_families(GrowableArray* methods) { + void get_discovered_families(GrowableArray* methods) { _families.extract_families_into(methods); } @@ -733,7 +829,7 @@ // Find all methods on this hierarchy that match this method // (name, signature). This class collects other families of this // method name. - StatefulMethodFamily* family = + StatefulGenericMethodFamily* family = _families.find_matching_or_create(md, _ctx); if (klass->is_interface()) { @@ -752,8 +848,8 @@ }; #ifndef PRODUCT -static void print_families( - GrowableArray* methods, Symbol* match) { +static void print_generic_families( + GrowableArray* methods, Symbol* match) { streamIndentor si(tty, 4); if (methods->length() == 0) { tty->indent(); @@ -761,21 +857,86 @@ } for (int i = 0; i < methods->length(); ++i) { tty->indent(); - MethodFamily* lm = methods->at(i); + GenericMethodFamily* lm = methods->at(i); if (lm->contains_signature(match)) { tty->print_cr(""); } else { tty->print_cr(""); } - lm->print_on(tty, 1); + lm->print_sig_on(tty, lm->get_generic_sig(), 1); } } #endif // ndef PRODUCT +static void create_overpasses( + GrowableArray* slots, InstanceKlass* klass, TRAPS); + +static void generate_generic_defaults( + InstanceKlass* klass, GrowableArray* empty_slots, + EmptyVtableSlot* slot, int current_slot_index, TRAPS) { + + if (slot->is_bound()) { +#ifndef PRODUCT + if (TraceDefaultMethods) { + streamIndentor si(tty, 4); + tty->indent().print_cr("Already bound to logical method:"); + GenericMethodFamily* lm = (GenericMethodFamily*)(slot->get_binding()); + lm->print_sig_on(tty, lm->get_generic_sig(), 1); + } +#endif // ndef PRODUCT + return; // covered by previous processing + } + + generic::DescriptorCache cache; + + generic::Context ctx(&cache); + FindMethodsByGenericSig visitor(&cache, slot->name(), &ctx, CHECK); + visitor.run(klass); + + GrowableArray discovered_families; + visitor.get_discovered_families(&discovered_families); + +#ifndef PRODUCT + if (TraceDefaultMethods) { + print_generic_families(&discovered_families, slot->signature()); + } +#endif // ndef PRODUCT + + // Find and populate any other slots that match the discovered families + for (int j = current_slot_index; j < empty_slots->length(); ++j) { + EmptyVtableSlot* open_slot = empty_slots->at(j); + + if (slot->name() == open_slot->name()) { + for (int k = 0; k < discovered_families.length(); ++k) { + GenericMethodFamily* lm = discovered_families.at(k); + + if (lm->contains_signature(open_slot->signature())) { + lm->determine_target(klass, CHECK); + open_slot->bind_family(lm); + } + } + } + } +} + +static void generate_erased_defaults( + InstanceKlass* klass, GrowableArray* empty_slots, + EmptyVtableSlot* slot, TRAPS) { + + // sets up a set of methods with the same exact erased signature + FindMethodsByErasedSig visitor(slot->name(), slot->signature()); + visitor.run(klass); + + MethodFamily* family; + visitor.get_discovered_family(&family); + if (family != NULL) { + family->determine_target(klass, CHECK); + slot->bind_family(family); + } +} + static void merge_in_new_methods(InstanceKlass* klass, GrowableArray* new_methods, TRAPS); -static void create_overpasses( - GrowableArray* slots, InstanceKlass* klass, TRAPS); // This is the guts of the default methods implementation. This is called just // after the classfile has been parsed if some ancestor has default methods. @@ -807,8 +968,6 @@ // whatever scope it's in. ResourceMark rm(THREAD); - generic::DescriptorCache cache; - // Keep entire hierarchy alive for the duration of the computation KeepAliveRegistrar keepAlive(THREAD); KeepAliveVisitor loadKeepAlive(&keepAlive); @@ -837,47 +996,13 @@ tty->print_cr(""); } #endif // ndef PRODUCT - if (slot->is_bound()) { -#ifndef PRODUCT - if (TraceDefaultMethods) { - streamIndentor si(tty, 4); - tty->indent().print_cr("Already bound to logical method:"); - slot->get_binding()->print_on(tty, 1); - } -#endif // ndef PRODUCT - continue; // covered by previous processing + + if (ParseGenericDefaults) { + generate_generic_defaults(klass, empty_slots, slot, i, CHECK); + } else { + generate_erased_defaults(klass, empty_slots, slot, CHECK); } - - generic::Context ctx(&cache); - FindMethodsByName visitor(&cache, slot->name(), &ctx, CHECK); - visitor.run(klass); - - GrowableArray discovered_families; - visitor.get_discovered_families(&discovered_families); - -#ifndef PRODUCT - if (TraceDefaultMethods) { - print_families(&discovered_families, slot->signature()); - } -#endif // ndef PRODUCT - - // Find and populate any other slots that match the discovered families - for (int j = i; j < empty_slots->length(); ++j) { - EmptyVtableSlot* open_slot = empty_slots->at(j); - - if (slot->name() == open_slot->name()) { - for (int k = 0; k < discovered_families.length(); ++k) { - MethodFamily* lm = discovered_families.at(k); - - if (lm->contains_signature(open_slot->signature())) { - lm->determine_target(klass, CHECK); - open_slot->bind_family(lm); - } - } - } - } - } - + } #ifndef PRODUCT if (TraceDefaultMethods) { tty->print_cr("Creating overpasses..."); @@ -893,7 +1018,6 @@ #endif // ndef PRODUCT } - /** * Generic analysis was used upon interface '_target' and found a unique * default method candidate with generic signature '_method_desc'. This @@ -912,16 +1036,84 @@ * the selected method along that path. */ class ShadowChecker : public HierarchyVisitor { - private: - generic::DescriptorCache* _cache; + protected: Thread* THREAD; InstanceKlass* _target; Symbol* _method_name; InstanceKlass* _method_holder; + bool _found_shadow; + + + public: + + ShadowChecker(Thread* thread, Symbol* name, InstanceKlass* holder, + InstanceKlass* target) + : THREAD(thread), _method_name(name), _method_holder(holder), + _target(target), _found_shadow(false) {} + + void* new_node_data(InstanceKlass* cls) { return NULL; } + void free_node_data(void* data) { return; } + + bool visit() { + InstanceKlass* ik = current_class(); + if (ik == _target && current_depth() == 1) { + return false; // This was the specified super -- no need to search it + } + if (ik == _method_holder || ik == _target) { + // We found a path that should be examined to see if it shadows _method + if (path_has_shadow()) { + _found_shadow = true; + cancel_iteration(); + } + return false; // no need to continue up hierarchy + } + return true; + } + + virtual bool path_has_shadow() = 0; + bool found_shadow() { return _found_shadow; } +}; + +// Used for Invokespecial. +// Invokespecial is allowed to invoke a concrete interface method +// and can be used to disambuiguate among qualified candidates, +// which are methods in immediate superinterfaces, +// but may not be used to invoke a candidate that would be shadowed +// from the perspective of the caller. +// Invokespecial is also used in the overpass generation today +// We re-run the shadowchecker because we can't distinguish this case, +// but it should return the same answer, since the overpass target +// is now the invokespecial caller. +class ErasedShadowChecker : public ShadowChecker { + private: + bool path_has_shadow() { + + for (int i = current_depth() - 1; i > 0; --i) { + InstanceKlass* ik = class_at_depth(i); + + if (ik->is_interface()) { + int end; + int start = ik->find_method_by_name(_method_name, &end); + if (start != -1) { + return true; + } + } + } + return false; + } + public: + + ErasedShadowChecker(Thread* thread, Symbol* name, InstanceKlass* holder, + InstanceKlass* target) + : ShadowChecker(thread, name, holder, target) {} +}; + +class GenericShadowChecker : public ShadowChecker { + private: + generic::DescriptorCache* _cache; generic::MethodDescriptor* _method_desc; - bool _found_shadow; bool path_has_shadow() { generic::Context ctx(_cache); @@ -950,104 +1142,42 @@ public: - ShadowChecker(generic::DescriptorCache* cache, Thread* thread, + GenericShadowChecker(generic::DescriptorCache* cache, Thread* thread, Symbol* name, InstanceKlass* holder, generic::MethodDescriptor* desc, InstanceKlass* target) - : _cache(cache), THREAD(thread), _method_name(name), _method_holder(holder), - _method_desc(desc), _target(target), _found_shadow(false) {} - - void* new_node_data(InstanceKlass* cls) { return NULL; } - void free_node_data(void* data) { return; } - - bool visit() { - InstanceKlass* ik = current_class(); - if (ik == _target && current_depth() == 1) { - return false; // This was the specified super -- no need to search it - } - if (ik == _method_holder || ik == _target) { - // We found a path that should be examined to see if it shadows _method - if (path_has_shadow()) { - _found_shadow = true; - cancel_iteration(); - } - return false; // no need to continue up hierarchy - } - return true; - } - - bool found_shadow() { return _found_shadow; } + : ShadowChecker(thread, name, holder, target) { + _cache = cache; + _method_desc = desc; + } }; -// This is called during linktime when we find an invokespecial call that -// refers to a direct superinterface. It indicates that we should find the -// default method in the hierarchy of that superinterface, and if that method -// would have been a candidate from the point of view of 'this' class, then we -// return that method. -Method* DefaultMethods::find_super_default( - Klass* cls, Klass* super, Symbol* method_name, Symbol* sig, TRAPS) { + - ResourceMark rm(THREAD); - - assert(cls != NULL && super != NULL, "Need real classes"); - - InstanceKlass* current_class = InstanceKlass::cast(cls); - InstanceKlass* direction = InstanceKlass::cast(super); +// Find the unique qualified candidate from the perspective of the super_class +// which is the resolved_klass, which must be an immediate superinterface +// of klass +Method* find_erased_super_default(InstanceKlass* current_class, InstanceKlass* super_class, Symbol* method_name, Symbol* sig, TRAPS) { - // Keep entire hierarchy alive for the duration of the computation - KeepAliveRegistrar keepAlive(THREAD); - KeepAliveVisitor loadKeepAlive(&keepAlive); - loadKeepAlive.run(current_class); + FindMethodsByErasedSig visitor(method_name, sig); + visitor.run(super_class); // find candidates from resolved_klass -#ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print_cr("Finding super default method %s.%s%s from %s", - direction->name()->as_C_string(), - method_name->as_C_string(), sig->as_C_string(), - current_class->name()->as_C_string()); - } -#endif // ndef PRODUCT + MethodFamily* family; + visitor.get_discovered_family(&family); - if (!direction->is_interface()) { - // We should not be here - return NULL; + if (family != NULL) { + family->determine_target(current_class, CHECK_NULL); // get target from current_class } - generic::DescriptorCache cache; - generic::Context ctx(&cache); - - // Prime the initial generic context for current -> direction - ctx.apply_type_arguments(current_class, direction, CHECK_NULL); - - FindMethodsByName visitor(&cache, method_name, &ctx, CHECK_NULL); - visitor.run(direction); - - GrowableArray families; - visitor.get_discovered_families(&families); - -#ifndef PRODUCT - if (TraceDefaultMethods) { - print_families(&families, sig); - } -#endif // ndef PRODUCT - - MethodFamily* selected_family = NULL; - - for (int i = 0; i < families.length(); ++i) { - MethodFamily* lm = families.at(i); - if (lm->contains_signature(sig)) { - lm->determine_target(current_class, CHECK_NULL); - selected_family = lm; - } - } - - if (selected_family->has_target()) { - Method* target = selected_family->get_selected_target(); + if (family->has_target()) { + Method* target = family->get_selected_target(); InstanceKlass* holder = InstanceKlass::cast(target->method_holder()); // Verify that the identified method is valid from the context of - // the current class - ShadowChecker checker(&cache, THREAD, target->name(), - holder, selected_family->descriptor(), direction); + // the current class, which is the caller class for invokespecial + // link resolution, i.e. ensure there it is not shadowed. + // You can use invokespecial to disambiguate interface methods, but + // you can not use it to skip over an interface method that would shadow it. + ErasedShadowChecker checker(THREAD, target->name(), holder, super_class); checker.run(current_class); if (checker.found_shadow()) { @@ -1061,20 +1191,143 @@ } else { #ifndef PRODUCT if (TraceDefaultMethods) { - tty->print(" Returning "); - print_method(tty, target, true); - tty->print_cr(""); + family->print_sig_on(tty, target->signature(), 1); } #endif // ndef PRODUCT return target; } } else { + assert(family->throws_exception(), "must have target or throw"); + THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), + family->get_exception_message()->as_C_string(), NULL); + } +} + +// super_class is assumed to be the direct super of current_class +Method* find_generic_super_default( InstanceKlass* current_class, + InstanceKlass* super_class, + Symbol* method_name, Symbol* sig, TRAPS) { + generic::DescriptorCache cache; + generic::Context ctx(&cache); + + // Prime the initial generic context for current -> super_class + ctx.apply_type_arguments(current_class, super_class, CHECK_NULL); + + FindMethodsByGenericSig visitor(&cache, method_name, &ctx, CHECK_NULL); + visitor.run(super_class); + + GrowableArray families; + visitor.get_discovered_families(&families); + +#ifndef PRODUCT + if (TraceDefaultMethods) { + print_generic_families(&families, sig); + } +#endif // ndef PRODUCT + + GenericMethodFamily* selected_family = NULL; + + for (int i = 0; i < families.length(); ++i) { + GenericMethodFamily* lm = families.at(i); + if (lm->contains_signature(sig)) { + lm->determine_target(current_class, CHECK_NULL); + selected_family = lm; + } + } + + if (selected_family->has_target()) { + Method* target = selected_family->get_selected_target(); + InstanceKlass* holder = InstanceKlass::cast(target->method_holder()); + + // Verify that the identified method is valid from the context of + // the current class + GenericShadowChecker checker(&cache, THREAD, target->name(), + holder, selected_family->descriptor(), super_class); + checker.run(current_class); + + if (checker.found_shadow()) { +#ifndef PRODUCT + if (TraceDefaultMethods) { + tty->print_cr(" Only candidate found was shadowed."); + } +#endif // ndef PRODUCT + THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), + "Accessible default method not found", NULL); + } else { + return target; + } + } else { assert(selected_family->throws_exception(), "must have target or throw"); THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), selected_family->get_exception_message()->as_C_string(), NULL); } } +// This is called during linktime when we find an invokespecial call that +// refers to a direct superinterface. It indicates that we should find the +// default method in the hierarchy of that superinterface, and if that method +// would have been a candidate from the point of view of 'this' class, then we +// return that method. +// This logic assumes that the super is a direct superclass of the caller +Method* DefaultMethods::find_super_default( + Klass* cls, Klass* super, Symbol* method_name, Symbol* sig, TRAPS) { + + ResourceMark rm(THREAD); + + assert(cls != NULL && super != NULL, "Need real classes"); + + InstanceKlass* current_class = InstanceKlass::cast(cls); + InstanceKlass* super_class = InstanceKlass::cast(super); + + // Keep entire hierarchy alive for the duration of the computation + KeepAliveRegistrar keepAlive(THREAD); + KeepAliveVisitor loadKeepAlive(&keepAlive); + loadKeepAlive.run(current_class); // get hierarchy from current class + +#ifndef PRODUCT + if (TraceDefaultMethods) { + tty->print_cr("Finding super default method %s.%s%s from %s", + super_class->name()->as_C_string(), + method_name->as_C_string(), sig->as_C_string(), + current_class->name()->as_C_string()); + } +#endif // ndef PRODUCT + + assert(super_class->is_interface(), "only call for default methods"); + + Method* target = NULL; + if (ParseGenericDefaults) { + target = find_generic_super_default(current_class, super_class, + method_name, sig, CHECK_NULL); + } else { + target = find_erased_super_default(current_class, super_class, + method_name, sig, CHECK_NULL); + } + +#ifndef PRODUCT + if (target != NULL) { + if (TraceDefaultMethods) { + tty->print(" Returning "); + print_method(tty, target, true); + tty->print_cr(""); + } + } +#endif // ndef PRODUCT + return target; +} + +#ifndef PRODUCT +// Return true is broad type is a covariant return of narrow type +static bool covariant_return_type(BasicType narrow, BasicType broad) { + if (narrow == broad) { + return true; + } + if (broad == T_OBJECT) { + return true; + } + return false; +} +#endif // ndef PRODUCT static int assemble_redirect( BytecodeConstantPool* cp, BytecodeBuffer* buffer, @@ -1103,7 +1356,7 @@ out.next(); } assert(out.at_return_type(), "Parameter counts do not match"); - assert(in.type() == out.type(), "Return types are not compatible"); + assert(covariant_return_type(out.type(), in.type()), "Return types are not compatible"); if (parameter_count == 1 && (in.type() == T_LONG || in.type() == T_DOUBLE)) { ++parameter_count; // need room for return value @@ -1144,10 +1397,15 @@ Symbol* sig, AccessFlags flags, int max_stack, int params, ConstMethod::MethodType mt, TRAPS) { - address code_start = static_cast
(bytecodes->adr_at(0)); - int code_length = bytecodes->length(); + address code_start = 0; + int code_length = 0; InlineTableSizes sizes; + if (bytecodes != NULL && bytecodes->length() > 0) { + code_start = static_cast
(bytecodes->adr_at(0)); + code_length = bytecodes->length(); + } + Method* m = Method::allocate(cp->pool_holder()->class_loader_data(), code_length, flags, &sizes, mt, CHECK_NULL); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/classfile/javaClasses.hpp --- a/src/share/vm/classfile/javaClasses.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/classfile/javaClasses.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -234,6 +234,7 @@ static GrowableArray* _fixup_mirror_list; static void set_init_lock(oop java_class, oop init_lock); + static void set_protection_domain(oop java_class, oop protection_domain); public: static void compute_offsets(); @@ -272,7 +273,6 @@ // Support for embedded per-class oops static oop protection_domain(oop java_class); - static void set_protection_domain(oop java_class, oop protection_domain); static oop init_lock(oop java_class); static objArrayOop signers(oop java_class); static void set_signers(oop java_class, objArrayOop signers); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -2017,12 +2017,6 @@ ALL_SINCE_SAVE_MARKS_CLOSURES(CFLS_OOP_SINCE_SAVE_MARKS_DEFN) - -void CompactibleFreeListSpace::object_iterate_since_last_GC(ObjectClosure* cl) { - // ugghh... how would one do this efficiently for a non-contiguous space? - guarantee(false, "NYI"); -} - bool CompactibleFreeListSpace::linearAllocationWouldFail() const { return _smallLinearAllocBlock._word_size == 0; } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -396,7 +396,6 @@ // iteration support for promotion void save_marks(); bool no_allocs_since_save_marks(); - void object_iterate_since_last_GC(ObjectClosure* cl); // iteration support for sweeping void save_sweep_limit() { diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -3130,26 +3130,6 @@ ALL_SINCE_SAVE_MARKS_CLOSURES(CMS_SINCE_SAVE_MARKS_DEFN) void -ConcurrentMarkSweepGeneration::object_iterate_since_last_GC(ObjectClosure* blk) -{ - // Not currently implemented; need to do the following. -- ysr. - // dld -- I think that is used for some sort of allocation profiler. So it - // really means the objects allocated by the mutator since the last - // GC. We could potentially implement this cheaply by recording only - // the direct allocations in a side data structure. - // - // I think we probably ought not to be required to support these - // iterations at any arbitrary point; I think there ought to be some - // call to enable/disable allocation profiling in a generation/space, - // and the iterator ought to return the objects allocated in the - // gen/space since the enable call, or the last iterator call (which - // will probably be at a GC.) That way, for gens like CM&S that would - // require some extra data structure to support this, we only pay the - // cost when it's in use... - cmsSpace()->object_iterate_since_last_GC(blk); -} - -void ConcurrentMarkSweepGeneration::younger_refs_iterate(OopsInGenClosure* cl) { cl->set_generation(this); younger_refs_in_space_iterate(_cmsSpace, cl); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp --- a/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -1273,7 +1273,6 @@ // Iteration support and related enquiries void save_marks(); bool no_allocs_since_save_marks(); - void object_iterate_since_last_GC(ObjectClosure* cl); void younger_refs_iterate(OopsInGenClosure* cl); // Iteration support specific to CMS generations diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -54,7 +54,6 @@ #include "memory/referenceProcessor.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.pcgc.inline.hpp" -#include "runtime/aprofiler.hpp" #include "runtime/vmThread.hpp" size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0; @@ -2665,11 +2664,6 @@ heap_region_iterate(&blk); } -void G1CollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) { - // FIXME: is this right? - guarantee(false, "object_iterate_since_last_GC not supported by G1 heap"); -} - // Calls a SpaceClosure on a HeapRegion. class SpaceClosureRegionClosure: public HeapRegionClosure { @@ -3598,8 +3592,6 @@ void G1CollectedHeap::gc_prologue(bool full /* Ignored */) { // always_do_update_barrier = false; assert(InlineCacheBuffer::is_empty(), "should have cleaned up ICBuffer"); - // Call allocation profiler - AllocationProfiler::iterate_since_last_gc(); // Fill TLAB's and such ensure_parsability(true); } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp --- a/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -1360,11 +1360,6 @@ object_iterate(cl); } - // Iterate over all objects allocated since the last collection, calling - // "cl.do_object" on each. The heap must have been initialized properly - // to support this function, or else this call will fail. - virtual void object_iterate_since_last_GC(ObjectClosure* cl); - // Iterate over all spaces in use in the heap, in ascending address order. virtual void space_iterate(SpaceClosure* cl); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/g1/g1MarkSweep.cpp --- a/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -43,7 +43,6 @@ #include "oops/instanceRefKlass.hpp" #include "oops/oop.inline.hpp" #include "prims/jvmtiExport.hpp" -#include "runtime/aprofiler.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/fprofiler.hpp" #include "runtime/synchronizer.hpp" diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/shared/gcTrace.cpp --- a/src/share/vm/gc_implementation/shared/gcTrace.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTrace.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -23,12 +23,14 @@ */ #include "precompiled.hpp" +#include "gc_implementation/shared/copyFailedInfo.hpp" #include "gc_implementation/shared/gcHeapSummary.hpp" #include "gc_implementation/shared/gcTimer.hpp" #include "gc_implementation/shared/gcTrace.hpp" -#include "gc_implementation/shared/copyFailedInfo.hpp" +#include "gc_implementation/shared/objectCountEventSender.hpp" #include "memory/heapInspection.hpp" #include "memory/referenceProcessorStats.hpp" +#include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" #if INCLUDE_ALL_GCS @@ -38,7 +40,7 @@ #define assert_unset_gc_id() assert(_shared_gc_info.id() == SharedGCInfo::UNSET_GCID, "GC already started?") #define assert_set_gc_id() assert(_shared_gc_info.id() != SharedGCInfo::UNSET_GCID, "GC not started?") -static jlong GCTracer_next_gc_id = 0; +static GCId GCTracer_next_gc_id = 0; static GCId create_new_gc_id() { return GCTracer_next_gc_id++; } @@ -91,26 +93,38 @@ } #if INCLUDE_SERVICES -void ObjectCountEventSenderClosure::do_cinfo(KlassInfoEntry* entry) { - if (should_send_event(entry)) { - send_event(entry); - } -} +class ObjectCountEventSenderClosure : public KlassInfoClosure { + const GCId _gc_id; + const double _size_threshold_percentage; + const size_t _total_size_in_words; + const jlong _timestamp; -void ObjectCountEventSenderClosure::send_event(KlassInfoEntry* entry) { - _gc_tracer->send_object_count_after_gc_event(entry->klass(), entry->count(), - entry->words() * BytesPerWord); -} + public: + ObjectCountEventSenderClosure(GCId gc_id, size_t total_size_in_words, jlong timestamp) : + _gc_id(gc_id), + _size_threshold_percentage(ObjectCountCutOffPercent / 100), + _total_size_in_words(total_size_in_words), + _timestamp(timestamp) + {} -bool ObjectCountEventSenderClosure::should_send_event(KlassInfoEntry* entry) const { - double percentage_of_heap = ((double) entry->words()) / _total_size_in_words; - return percentage_of_heap > _size_threshold_percentage; -} + virtual void do_cinfo(KlassInfoEntry* entry) { + if (should_send_event(entry)) { + ObjectCountEventSender::send(entry, _gc_id, _timestamp); + } + } + + private: + bool should_send_event(const KlassInfoEntry* entry) const { + double percentage_of_heap = ((double) entry->words()) / _total_size_in_words; + return percentage_of_heap >= _size_threshold_percentage; + } +}; void GCTracer::report_object_count_after_gc(BoolObjectClosure* is_alive_cl) { assert_set_gc_id(); + assert(is_alive_cl != NULL, "Must supply function to check liveness"); - if (should_send_object_count_after_gc_event()) { + if (ObjectCountEventSender::should_send_event()) { ResourceMark rm; KlassInfoTable cit(false); @@ -118,12 +132,13 @@ HeapInspection hi(false, false, false, NULL); hi.populate_table(&cit, is_alive_cl); - ObjectCountEventSenderClosure event_sender(this, cit.size_of_instances_in_words()); + jlong timestamp = os::elapsed_counter(); + ObjectCountEventSenderClosure event_sender(_shared_gc_info.id(), cit.size_of_instances_in_words(), timestamp); cit.iterate(&event_sender); } } } -#endif +#endif // INCLUDE_SERVICES void GCTracer::report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const { assert_set_gc_id(); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/shared/gcTrace.hpp --- a/src/share/vm/gc_implementation/shared/gcTrace.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTrace.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -30,7 +30,6 @@ #include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/copyFailedInfo.hpp" #include "memory/allocation.hpp" -#include "memory/klassInfoClosure.hpp" #include "memory/referenceType.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/g1/g1YCTypes.hpp" @@ -113,7 +112,6 @@ #endif // INCLUDE_ALL_GCS class GCTracer : public ResourceObj { - friend class ObjectCountEventSenderClosure; protected: SharedGCInfo _shared_gc_info; @@ -123,7 +121,6 @@ void report_gc_heap_summary(GCWhen::Type when, const GCHeapSummary& heap_summary, const MetaspaceSummary& meta_space_summary) const; void report_gc_reference_stats(const ReferenceProcessorStats& rp) const; void report_object_count_after_gc(BoolObjectClosure* object_filter) NOT_SERVICES_RETURN; - bool has_reported_gc_start() const; protected: @@ -137,25 +134,6 @@ void send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const; void send_reference_stats_event(ReferenceType type, size_t count) const; void send_phase_events(TimePartitions* time_partitions) const; - void send_object_count_after_gc_event(Klass* klass, jlong count, julong total_size) const NOT_SERVICES_RETURN; - bool should_send_object_count_after_gc_event() const; -}; - -class ObjectCountEventSenderClosure : public KlassInfoClosure { - GCTracer* _gc_tracer; - const double _size_threshold_percentage; - const size_t _total_size_in_words; - public: - ObjectCountEventSenderClosure(GCTracer* gc_tracer, size_t total_size_in_words) : - _gc_tracer(gc_tracer), - _size_threshold_percentage(ObjectCountCutOffPercent / 100), - _total_size_in_words(total_size_in_words) - {} - virtual void do_cinfo(KlassInfoEntry* entry); - protected: - virtual void send_event(KlassInfoEntry* entry); - private: - bool should_send_event(KlassInfoEntry* entry) const; }; class YoungGCTracer : public GCTracer { diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/shared/gcTraceSend.cpp --- a/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -123,27 +123,6 @@ } } -#if INCLUDE_SERVICES -void GCTracer::send_object_count_after_gc_event(Klass* klass, jlong count, julong total_size) const { - EventObjectCountAfterGC e; - if (e.should_commit()) { - e.set_gcId(_shared_gc_info.id()); - e.set_class(klass); - e.set_count(count); - e.set_totalSize(total_size); - e.commit(); - } -} -#endif - -bool GCTracer::should_send_object_count_after_gc_event() const { -#if INCLUDE_TRACE - return Tracing::is_event_enabled(EventObjectCountAfterGC::eventId); -#else - return false; -#endif -} - #if INCLUDE_ALL_GCS void G1NewTracer::send_g1_young_gc_event() { EventGCG1GarbageCollection e(UNTIMED); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/shared/objectCountEventSender.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + + +#include "precompiled.hpp" +#include "gc_implementation/shared/objectCountEventSender.hpp" +#include "memory/heapInspection.hpp" +#include "trace/tracing.hpp" +#include "utilities/globalDefinitions.hpp" + +#if INCLUDE_SERVICES + +void ObjectCountEventSender::send(const KlassInfoEntry* entry, GCId gc_id, jlong timestamp) { + assert(Tracing::is_event_enabled(EventObjectCountAfterGC::eventId), + "Only call this method if the event is enabled"); + + EventObjectCountAfterGC event(UNTIMED); + event.set_gcId(gc_id); + event.set_class(entry->klass()); + event.set_count(entry->count()); + event.set_totalSize(entry->words() * BytesPerWord); + event.set_endtime(timestamp); + event.commit(); +} + +bool ObjectCountEventSender::should_send_event() { +#if INCLUDE_TRACE + return Tracing::is_event_enabled(EventObjectCountAfterGC::eventId); +#else + return false; +#endif // INCLUDE_TRACE +} + +#endif // INCLUDE_SERVICES diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_implementation/shared/objectCountEventSender.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP +#define SHARE_VM_OBJECT_COUNT_EVENT_SENDER_HPP + +#include "gc_implementation/shared/gcTrace.hpp" +#include "memory/allocation.hpp" +#include "utilities/macros.hpp" + +#if INCLUDE_SERVICES + +class KlassInfoEntry; + +class ObjectCountEventSender : public AllStatic { + public: + static void send(const KlassInfoEntry* entry, GCId gc_id, jlong timestamp); + static bool should_send_event(); +}; + +#endif // INCLUDE_SERVICES + +#endif // SHARE_VM_OBJECT_COUNT_EVENT_SENDER diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/gc_interface/collectedHeap.cpp --- a/src/share/vm/gc_interface/collectedHeap.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/gc_interface/collectedHeap.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -85,16 +85,16 @@ MetaspaceSummary CollectedHeap::create_metaspace_summary() { const MetaspaceSizes meta_space( - 0, /*MetaspaceAux::capacity_in_bytes(),*/ - 0, /*MetaspaceAux::used_in_bytes(),*/ + MetaspaceAux::allocated_capacity_bytes(), + MetaspaceAux::allocated_used_bytes(), MetaspaceAux::reserved_in_bytes()); const MetaspaceSizes data_space( - 0, /*MetaspaceAux::capacity_in_bytes(Metaspace::NonClassType),*/ - 0, /*MetaspaceAux::used_in_bytes(Metaspace::NonClassType),*/ + MetaspaceAux::allocated_capacity_bytes(Metaspace::NonClassType), + MetaspaceAux::allocated_used_bytes(Metaspace::NonClassType), MetaspaceAux::reserved_in_bytes(Metaspace::NonClassType)); const MetaspaceSizes class_space( - 0, /*MetaspaceAux::capacity_in_bytes(Metaspace::ClassType),*/ - 0, /*MetaspaceAux::used_in_bytes(Metaspace::ClassType),*/ + MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType), + MetaspaceAux::allocated_used_bytes(Metaspace::ClassType), MetaspaceAux::reserved_in_bytes(Metaspace::ClassType)); return MetaspaceSummary(meta_space, data_space, class_space); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/allocation.cpp --- a/src/share/vm/memory/allocation.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/allocation.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -236,10 +236,11 @@ size_t _num_used; // number of chunks currently checked out const size_t _size; // size of each chunk (must be uniform) - // Our three static pools + // Our four static pools static ChunkPool* _large_pool; static ChunkPool* _medium_pool; static ChunkPool* _small_pool; + static ChunkPool* _tiny_pool; // return first element or null void* get_first() { @@ -319,15 +320,18 @@ static ChunkPool* large_pool() { assert(_large_pool != NULL, "must be initialized"); return _large_pool; } static ChunkPool* medium_pool() { assert(_medium_pool != NULL, "must be initialized"); return _medium_pool; } static ChunkPool* small_pool() { assert(_small_pool != NULL, "must be initialized"); return _small_pool; } + static ChunkPool* tiny_pool() { assert(_tiny_pool != NULL, "must be initialized"); return _tiny_pool; } static void initialize() { _large_pool = new ChunkPool(Chunk::size + Chunk::aligned_overhead_size()); _medium_pool = new ChunkPool(Chunk::medium_size + Chunk::aligned_overhead_size()); _small_pool = new ChunkPool(Chunk::init_size + Chunk::aligned_overhead_size()); + _tiny_pool = new ChunkPool(Chunk::tiny_size + Chunk::aligned_overhead_size()); } static void clean() { enum { BlocksToKeep = 5 }; + _tiny_pool->free_all_but(BlocksToKeep); _small_pool->free_all_but(BlocksToKeep); _medium_pool->free_all_but(BlocksToKeep); _large_pool->free_all_but(BlocksToKeep); @@ -337,6 +341,7 @@ ChunkPool* ChunkPool::_large_pool = NULL; ChunkPool* ChunkPool::_medium_pool = NULL; ChunkPool* ChunkPool::_small_pool = NULL; +ChunkPool* ChunkPool::_tiny_pool = NULL; void chunkpool_init() { ChunkPool::initialize(); @@ -376,6 +381,7 @@ case Chunk::size: return ChunkPool::large_pool()->allocate(bytes, alloc_failmode); case Chunk::medium_size: return ChunkPool::medium_pool()->allocate(bytes, alloc_failmode); case Chunk::init_size: return ChunkPool::small_pool()->allocate(bytes, alloc_failmode); + case Chunk::tiny_size: return ChunkPool::tiny_pool()->allocate(bytes, alloc_failmode); default: { void* p = os::malloc(bytes, mtChunk, CALLER_PC); if (p == NULL && alloc_failmode == AllocFailStrategy::EXIT_OOM) { @@ -392,6 +398,7 @@ case Chunk::size: ChunkPool::large_pool()->free(c); break; case Chunk::medium_size: ChunkPool::medium_pool()->free(c); break; case Chunk::init_size: ChunkPool::small_pool()->free(c); break; + case Chunk::tiny_size: ChunkPool::tiny_pool()->free(c); break; default: os::free(c, mtChunk); } } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/allocation.hpp --- a/src/share/vm/memory/allocation.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/allocation.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -353,7 +353,8 @@ slack = 20, // suspected sizeof(Chunk) + internal malloc headers #endif - init_size = 1*K - slack, // Size of first chunk + tiny_size = 256 - slack, // Size of first chunk (tiny) + init_size = 1*K - slack, // Size of first chunk (normal aka small) medium_size= 10*K - slack, // Size of medium-sized chunk size = 32*K - slack, // Default size of an Arena chunk (following the first) non_pool_size = init_size + 32 // An initial size which is not one of above diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/defNewGeneration.cpp --- a/src/share/vm/memory/defNewGeneration.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/defNewGeneration.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -450,11 +450,6 @@ } } -void DefNewGeneration::object_iterate_since_last_GC(ObjectClosure* cl) { - // $$$ This may be wrong in case of "scavenge failure"? - eden()->object_iterate(cl); -} - void DefNewGeneration::younger_refs_iterate(OopsInGenClosure* cl) { assert(false, "NYI -- are you sure you want to call this?"); } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/defNewGeneration.hpp --- a/src/share/vm/memory/defNewGeneration.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/defNewGeneration.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -252,7 +252,6 @@ // Iteration void object_iterate(ObjectClosure* blk); - void object_iterate_since_last_GC(ObjectClosure* cl); void younger_refs_iterate(OopsInGenClosure* cl); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/genCollectedHeap.cpp --- a/src/share/vm/memory/genCollectedHeap.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/genCollectedHeap.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -42,7 +42,6 @@ #include "memory/space.hpp" #include "oops/oop.inline.hpp" #include "oops/oop.inline2.hpp" -#include "runtime/aprofiler.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/fprofiler.hpp" #include "runtime/handles.hpp" @@ -873,12 +872,6 @@ } } -void GenCollectedHeap::object_iterate_since_last_GC(ObjectClosure* cl) { - for (int i = 0; i < _n_gens; i++) { - _gens[i]->object_iterate_since_last_GC(cl); - } -} - Space* GenCollectedHeap::space_containing(const void* addr) const { for (int i = 0; i < _n_gens; i++) { Space* res = _gens[i]->space_containing(addr); @@ -1186,8 +1179,6 @@ CollectedHeap::accumulate_statistics_all_tlabs(); ensure_parsability(true); // retire TLABs - // Call allocation profiler - AllocationProfiler::iterate_since_last_gc(); // Walk generations GenGCPrologueClosure blk(full); generation_iterate(&blk, false); // not old-to-young. diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/genCollectedHeap.hpp --- a/src/share/vm/memory/genCollectedHeap.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/genCollectedHeap.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -222,7 +222,6 @@ void oop_iterate(MemRegion mr, ExtendedOopClosure* cl); void object_iterate(ObjectClosure* cl); void safe_object_iterate(ObjectClosure* cl); - void object_iterate_since_last_GC(ObjectClosure* cl); Space* space_containing(const void* addr) const; // A CollectedHeap is divided into a dense sequence of "blocks"; that is, diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/generation.cpp --- a/src/share/vm/memory/generation.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/generation.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -811,16 +811,6 @@ blk->do_space(_the_space); } -void OneContigSpaceCardGeneration::object_iterate_since_last_GC(ObjectClosure* blk) { - // Deal with delayed initialization of _the_space, - // and lack of initialization of _last_gc. - if (_last_gc.space() == NULL) { - assert(the_space() != NULL, "shouldn't be NULL"); - _last_gc = the_space()->bottom_mark(); - } - the_space()->object_iterate_from(_last_gc, blk); -} - void OneContigSpaceCardGeneration::younger_refs_iterate(OopsInGenClosure* blk) { blk->set_generation(this); younger_refs_in_space_iterate(_the_space, blk); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/generation.hpp --- a/src/share/vm/memory/generation.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/generation.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -551,12 +551,6 @@ // the heap. This defaults to object_iterate() unless overridden. virtual void safe_object_iterate(ObjectClosure* cl); - // Iterate over all objects allocated in the generation since the last - // collection, calling "cl.do_object" on each. The generation must have - // been initialized properly to support this function, or else this call - // will fail. - virtual void object_iterate_since_last_GC(ObjectClosure* cl) = 0; - // Apply "cl->do_oop" to (the address of) all and only all the ref fields // in the current generation that contain pointers to objects in younger // generations. Objects allocated since the last "save_marks" call are @@ -724,7 +718,6 @@ // Iteration void object_iterate(ObjectClosure* blk); void space_iterate(SpaceClosure* blk, bool usedOnly = false); - void object_iterate_since_last_GC(ObjectClosure* cl); void younger_refs_iterate(OopsInGenClosure* blk); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/heapInspection.hpp --- a/src/share/vm/memory/heapInspection.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/heapInspection.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -26,7 +26,6 @@ #define SHARE_VM_MEMORY_HEAPINSPECTION_HPP #include "memory/allocation.inline.hpp" -#include "memory/klassInfoClosure.hpp" #include "oops/oop.inline.hpp" #include "oops/annotations.hpp" #include "utilities/macros.hpp" @@ -204,6 +203,12 @@ const char* name() const; }; +class KlassInfoClosure : public StackObj { + public: + // Called for each KlassInfoEntry. + virtual void do_cinfo(KlassInfoEntry* cie) = 0; +}; + class KlassInfoBucket: public CHeapObj { private: KlassInfoEntry* _list; diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/klassInfoClosure.hpp --- a/src/share/vm/memory/klassInfoClosure.hpp Thu Jul 11 10:13:37 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#ifndef SHARE_VM_MEMORY_KLASSINFOCLOSURE_HPP -#define SHARE_VM_MEMORY_KLASSINFOCLOSURE_HPP - -class KlassInfoEntry; - -class KlassInfoClosure : public StackObj { - public: - // Called for each KlassInfoEntry. - virtual void do_cinfo(KlassInfoEntry* cie) = 0; -}; - -#endif // SHARE_VM_MEMORY_KLASSINFOCLOSURE_HPP diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/sharedHeap.hpp --- a/src/share/vm/memory/sharedHeap.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/sharedHeap.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -166,11 +166,6 @@ // Same as above, restricted to a memory region. virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0; - // Iterate over all objects allocated since the last collection, calling - // "cl->do_object" on each. The heap must have been initialized properly - // to support this function, or else this call will fail. - virtual void object_iterate_since_last_GC(ObjectClosure* cl) = 0; - // Iterate over all spaces in use in the heap, in an undefined order. virtual void space_iterate(SpaceClosure* cl) = 0; diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/memory/universe.cpp --- a/src/share/vm/memory/universe.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/memory/universe.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -52,7 +52,6 @@ #include "oops/oop.inline.hpp" #include "oops/typeArrayKlass.hpp" #include "prims/jvmtiRedefineClassesTrace.hpp" -#include "runtime/aprofiler.hpp" #include "runtime/arguments.hpp" #include "runtime/deoptimization.hpp" #include "runtime/fprofiler.hpp" diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/oops/arrayKlass.cpp --- a/src/share/vm/oops/arrayKlass.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/oops/arrayKlass.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -71,7 +71,6 @@ } ArrayKlass::ArrayKlass(Symbol* name) { - set_alloc_size(0); set_name(name); set_super(Universe::is_bootstrapping() ? (Klass*)NULL : SystemDictionary::Object_klass()); @@ -161,12 +160,6 @@ } } - -void ArrayKlass::with_array_klasses_do(void f(Klass* k)) { - array_klasses_do(f); -} - - // GC support void ArrayKlass::oops_do(OopClosure* cl) { diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/oops/arrayKlass.hpp --- a/src/share/vm/oops/arrayKlass.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/oops/arrayKlass.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -39,7 +39,6 @@ Klass* volatile _higher_dimension; // Refers the (n+1)'th-dimensional array (if present). Klass* volatile _lower_dimension; // Refers the (n-1)'th-dimensional array (if present). int _vtable_len; // size of vtable for this klass - juint _alloc_size; // allocation profiling support oop _component_mirror; // component type, as a java/lang/Class protected: @@ -65,10 +64,6 @@ void set_lower_dimension(Klass* k) { _lower_dimension = k; } Klass** adr_lower_dimension() { return (Klass**)&this->_lower_dimension;} - // Allocation profiling support - juint alloc_size() const { return _alloc_size; } - void set_alloc_size(juint n) { _alloc_size = n; } - // offset of first element, including any padding for the sake of alignment int array_header_in_bytes() const { return layout_helper_header_size(layout_helper()); } int log2_element_size() const { return layout_helper_log2_element_size(layout_helper()); } @@ -126,7 +121,6 @@ // Iterators void array_klasses_do(void f(Klass* k)); void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); - void with_array_klasses_do(void f(Klass* k)); // GC support virtual void oops_do(OopClosure* cl); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/oops/instanceKlass.cpp --- a/src/share/vm/oops/instanceKlass.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/oops/instanceKlass.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -1321,12 +1321,6 @@ ArrayKlass::cast(array_klasses())->array_klasses_do(f); } - -void InstanceKlass::with_array_klasses_do(void f(Klass* k)) { - f(this); - array_klasses_do(f); -} - #ifdef ASSERT static int linear_search(Array* methods, Symbol* name, Symbol* signature) { int len = methods->length(); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/oops/instanceKlass.hpp --- a/src/share/vm/oops/instanceKlass.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/oops/instanceKlass.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -794,7 +794,6 @@ void methods_do(void f(Method* method)); void array_klasses_do(void f(Klass* k)); void array_klasses_do(void f(Klass* k, TRAPS), TRAPS); - void with_array_klasses_do(void f(Klass* k)); bool super_types_do(SuperTypeClosure* blk); // Casting from Klass* @@ -874,10 +873,6 @@ } } - // Allocation profiling support - juint alloc_size() const { return _alloc_count * size_helper(); } - void set_alloc_size(juint n) {} - // Use this to return the size of an instance in heap words: int size_helper() const { return layout_helper_to_size_helper(layout_helper()); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/oops/klass.cpp --- a/src/share/vm/oops/klass.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/oops/klass.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -168,7 +168,6 @@ set_subklass(NULL); set_next_sibling(NULL); set_next_link(NULL); - set_alloc_count(0); TRACE_INIT_ID(this); set_prototype_header(markOopDesc::prototype()); @@ -543,12 +542,6 @@ return NULL; } - -void Klass::with_array_klasses_do(void f(Klass* k)) { - f(this); -} - - oop Klass::class_loader() const { return class_loader_data()->class_loader(); } const char* Klass::external_name() const { diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/oops/klass.hpp --- a/src/share/vm/oops/klass.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/oops/klass.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -79,7 +79,6 @@ // [last_biased_lock_bulk_revocation_time] (64 bits) // [prototype_header] // [biased_lock_revocation_count] -// [alloc_count ] // [_modified_oops] // [_accumulated_modified_oops] // [trace_id] @@ -171,8 +170,6 @@ markOop _prototype_header; // Used when biased locking is both enabled and disabled for this type jint _biased_lock_revocation_count; - juint _alloc_count; // allocation profiling support - TRACE_DEFINE_KLASS_TRACE_ID; // Remembered sets support for the oops in the klasses. @@ -290,11 +287,6 @@ void set_next_sibling(Klass* s); public: - // Allocation profiling support - juint alloc_count() const { return _alloc_count; } - void set_alloc_count(juint n) { _alloc_count = n; } - virtual juint alloc_size() const = 0; - virtual void set_alloc_size(juint n) = 0; // Compiler support static ByteSize super_offset() { return in_ByteSize(offset_of(Klass, _super)); } @@ -677,7 +669,6 @@ #endif // INCLUDE_ALL_GCS virtual void array_klasses_do(void f(Klass* k)) {} - virtual void with_array_klasses_do(void f(Klass* k)); // Return self, except for abstract classes with exactly 1 // implementor. Then return the 1 concrete implementation. diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/prims/jni.cpp --- a/src/share/vm/prims/jni.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/prims/jni.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -5097,7 +5097,7 @@ // function used to determine this will always return false. Atomic::xchg // does not have this problem. if (Atomic::xchg(1, &vm_created) == 1) { - return JNI_ERR; // already created, or create attempt in progress + return JNI_EEXIST; // already created, or create attempt in progress } if (Atomic::xchg(0, &safe_to_recreate_vm) == 0) { return JNI_ERR; // someone tried and failed and retry not allowed. @@ -5138,9 +5138,21 @@ event.commit(); } +#ifndef PRODUCT + #ifndef TARGET_OS_FAMILY_windows + #define CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(f) f() + #endif + // Check if we should compile all classes on bootclasspath - NOT_PRODUCT(if (CompileTheWorld) ClassLoader::compile_the_world();) - NOT_PRODUCT(if (ReplayCompiles) ciReplay::replay(thread);) + if (CompileTheWorld) ClassLoader::compile_the_world(); + if (ReplayCompiles) ciReplay::replay(thread); + + // Some platforms (like Win*) need a wrapper around these test + // functions in order to properly handle error conditions. + CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(test_error_handler); + CALL_TEST_FUNC_WITH_WRAPPER_IF_NEEDED(execute_internal_vm_tests); +#endif + // Since this is not a JVM_ENTRY we have to set the thread state manually before leaving. ThreadStateTransition::transition_and_fence(thread, _thread_in_vm, _thread_in_native); } else { @@ -5157,8 +5169,6 @@ OrderAccess::release_store(&vm_created, 0); } - NOT_PRODUCT(test_error_handler(ErrorHandlerTest)); - NOT_PRODUCT(execute_internal_vm_tests()); return result; } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/prims/jvm.cpp --- a/src/share/vm/prims/jvm.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/prims/jvm.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -1121,26 +1121,6 @@ JVM_END -// Obsolete since 1.2 (Class.setProtectionDomain removed), although -// still defined in core libraries as of 1.5. -JVM_ENTRY(void, JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain)) - JVMWrapper("JVM_SetProtectionDomain"); - if (JNIHandles::resolve(cls) == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } - if (!java_lang_Class::is_primitive(JNIHandles::resolve(cls))) { - // Call is ignored for primitive types - Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve(cls)); - - // cls won't be an array, as this called only from ClassLoader.defineClass - if (k->oop_is_instance()) { - oop pd = JNIHandles::resolve(protection_domain); - assert(pd == NULL || pd->is_oop(), "just checking"); - java_lang_Class::set_protection_domain(k->java_mirror(), pd); - } - } -JVM_END - static bool is_authorized(Handle context, instanceKlassHandle klass, TRAPS) { // If there is a security manager and protection domain, check the access // in the protection domain, otherwise it is authorized. diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/prims/jvm.h --- a/src/share/vm/prims/jvm.h Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/prims/jvm.h Fri Jul 12 16:53:39 2013 -0700 @@ -471,9 +471,6 @@ JNIEXPORT jobject JNICALL JVM_GetProtectionDomain(JNIEnv *env, jclass cls); -JNIEXPORT void JNICALL -JVM_SetProtectionDomain(JNIEnv *env, jclass cls, jobject protection_domain); - JNIEXPORT jboolean JNICALL JVM_IsArrayClass(JNIEnv *env, jclass cls); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/aprofiler.cpp --- a/src/share/vm/runtime/aprofiler.cpp Thu Jul 11 10:13:37 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "precompiled.hpp" -#include "classfile/systemDictionary.hpp" -#include "gc_interface/collectedHeap.inline.hpp" -#include "memory/resourceArea.hpp" -#include "memory/space.hpp" -#include "oops/oop.inline.hpp" -#include "oops/oop.inline2.hpp" -#include "runtime/aprofiler.hpp" - - -bool AllocationProfiler::_active = false; -GrowableArray* AllocationProfiler::_print_array = NULL; - - -class AllocProfClosure : public ObjectClosure { - public: - void do_object(oop obj) { - Klass* k = obj->klass(); - k->set_alloc_count(k->alloc_count() + 1); - k->set_alloc_size(k->alloc_size() + obj->size()); - } -}; - - -void AllocationProfiler::iterate_since_last_gc() { - if (is_active()) { - AllocProfClosure blk; - GenCollectedHeap* heap = GenCollectedHeap::heap(); - heap->object_iterate_since_last_GC(&blk); - } -} - - -void AllocationProfiler::engage() { - _active = true; -} - - -void AllocationProfiler::disengage() { - _active = false; -} - - -void AllocationProfiler::add_class_to_array(Klass* k) { - _print_array->append(k); -} - - -void AllocationProfiler::add_classes_to_array(Klass* k) { - // Iterate over klass and all array klasses for klass - k->with_array_klasses_do(&AllocationProfiler::add_class_to_array); -} - - -int AllocationProfiler::compare_classes(Klass** k1, Klass** k2) { - // Sort by total allocation size - return (*k2)->alloc_size() - (*k1)->alloc_size(); -} - - -int AllocationProfiler::average(size_t alloc_size, int alloc_count) { - return (int) ((double) (alloc_size * BytesPerWord) / MAX2(alloc_count, 1) + 0.5); -} - - -void AllocationProfiler::sort_and_print_array(size_t cutoff) { - _print_array->sort(&AllocationProfiler::compare_classes); - tty->print_cr("________________Size" - "__Instances" - "__Average" - "__Class________________"); - size_t total_alloc_size = 0; - int total_alloc_count = 0; - for (int index = 0; index < _print_array->length(); index++) { - Klass* k = _print_array->at(index); - size_t alloc_size = k->alloc_size(); - if (alloc_size > cutoff) { - int alloc_count = k->alloc_count(); -#ifdef PRODUCT - const char* name = k->external_name(); -#else - const char* name = k->internal_name(); -#endif - tty->print_cr("%20u %10u %8u %s", - alloc_size * BytesPerWord, - alloc_count, - average(alloc_size, alloc_count), - name); - total_alloc_size += alloc_size; - total_alloc_count += alloc_count; - } - k->set_alloc_count(0); - k->set_alloc_size(0); - } - tty->print_cr("%20u %10u %8u --total--", - total_alloc_size * BytesPerWord, - total_alloc_count, - average(total_alloc_size, total_alloc_count)); - tty->cr(); -} - - -void AllocationProfiler::print(size_t cutoff) { - ResourceMark rm; - assert(!is_active(), "AllocationProfiler cannot be active while printing profile"); - - tty->cr(); - tty->print_cr("Allocation profile (sizes in bytes, cutoff = " SIZE_FORMAT " bytes):", cutoff * BytesPerWord); - tty->cr(); - - // Print regular instance klasses and basic type array klasses - _print_array = new GrowableArray(SystemDictionary::number_of_classes()*2); - SystemDictionary::classes_do(&add_classes_to_array); - Universe::basic_type_classes_do(&add_classes_to_array); - sort_and_print_array(cutoff); - - // This used to print metadata in the permgen but since there isn't a permgen - // anymore, it is not yet implemented. -} diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/aprofiler.hpp --- a/src/share/vm/runtime/aprofiler.hpp Thu Jul 11 10:13:37 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/* - * 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_RUNTIME_APROFILER_HPP -#define SHARE_VM_RUNTIME_APROFILER_HPP - -#include "memory/allocation.hpp" -#include "memory/universe.hpp" -#include "oops/klass.hpp" -#include "utilities/top.hpp" - -// A simple allocation profiler for Java. The profiler collects and prints -// the number and total size of instances allocated per class, including -// array classes. -// -// The profiler is currently global for all threads. It can be changed to a -// per threads profiler by keeping a more elaborate data structure and calling -// iterate_since_last_scavenge at thread switches. - - -class AllocationProfiler: AllStatic { - friend class GenCollectedHeap; - friend class G1CollectedHeap; - friend class MarkSweep; - private: - static bool _active; // tells whether profiler is active - static GrowableArray* _print_array; // temporary array for printing - - // Utility printing functions - static void add_class_to_array(Klass* k); - static void add_classes_to_array(Klass* k); - static int compare_classes(Klass** k1, Klass** k2); - static int average(size_t alloc_size, int alloc_count); - static void sort_and_print_array(size_t cutoff); - - // Call for collecting allocation information. Called at scavenge, mark-sweep and disengage. - static void iterate_since_last_gc(); - - public: - // Start profiler - static void engage(); - // Stop profiler - static void disengage(); - // Tells whether profiler is active - static bool is_active() { return _active; } - // Print profile - static void print(size_t cutoff); // Cutoff in total allocation size (in words) -}; - -#endif // SHARE_VM_RUNTIME_APROFILER_HPP diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/arguments.cpp --- a/src/share/vm/runtime/arguments.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/arguments.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -68,7 +68,6 @@ SystemProperty* Arguments::_system_properties = NULL; const char* Arguments::_gc_log_filename = NULL; bool Arguments::_has_profile = false; -bool Arguments::_has_alloc_profile = false; uintx Arguments::_min_heap_size = 0; Arguments::Mode Arguments::_mode = _mixed; bool Arguments::_java_compiler = false; @@ -261,6 +260,9 @@ { "PrintRevisitStats", JDK_Version::jdk(8), JDK_Version::jdk(9) }, { "UseVectoredExceptions", JDK_Version::jdk(8), JDK_Version::jdk(9) }, { "UseSplitVerifier", JDK_Version::jdk(8), JDK_Version::jdk(9) }, + { "UseISM", JDK_Version::jdk(8), JDK_Version::jdk(9) }, + { "UsePermISM", JDK_Version::jdk(8), JDK_Version::jdk(9) }, + { "UseMPSS", JDK_Version::jdk(8), JDK_Version::jdk(9) }, #ifdef PRODUCT { "DesiredMethodLimit", JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) }, @@ -1855,8 +1857,13 @@ "please refer to the release notes for the combinations " "allowed\n"); status = false; + } else if (ReservedCodeCacheSize > 2*G) { + // Code cache size larger than MAXINT is not supported. + jio_fprintf(defaultStream::error_stream(), + "Invalid ReservedCodeCacheSize=%dM. Must be at most %uM.\n", ReservedCodeCacheSize/M, + (2*G)/M); + status = false; } - return status; } @@ -1986,23 +1993,6 @@ status = status && check_gc_consistency(); status = status && check_stack_pages(); - if (_has_alloc_profile) { - if (UseParallelGC || UseParallelOldGC) { - jio_fprintf(defaultStream::error_stream(), - "error: invalid argument combination.\n" - "Allocation profiling (-Xaprof) cannot be used together with " - "Parallel GC (-XX:+UseParallelGC or -XX:+UseParallelOldGC).\n"); - status = false; - } - if (UseConcMarkSweepGC) { - jio_fprintf(defaultStream::error_stream(), - "error: invalid argument combination.\n" - "Allocation profiling (-Xaprof) cannot be used together with " - "the CMS collector (-XX:+UseConcMarkSweepGC).\n"); - status = false; - } - } - if (CMSIncrementalMode) { if (!UseConcMarkSweepGC) { jio_fprintf(defaultStream::error_stream(), @@ -2239,8 +2229,13 @@ "Invalid ReservedCodeCacheSize=%dK. Must be at least %uK.\n", ReservedCodeCacheSize/K, min_code_cache_size/K); status = false; + } else if (ReservedCodeCacheSize > 2*G) { + // Code cache size larger than MAXINT is not supported. + jio_fprintf(defaultStream::error_stream(), + "Invalid ReservedCodeCacheSize=%dM. Must be at most %uM.\n", ReservedCodeCacheSize/M, + (2*G)/M); + status = false; } - return status; } @@ -2700,9 +2695,6 @@ "Flat profiling is not supported in this VM.\n"); return JNI_ERR; #endif // INCLUDE_FPROF - // -Xaprof - } else if (match_option(option, "-Xaprof", &tail)) { - _has_alloc_profile = true; // -Xconcurrentio } else if (match_option(option, "-Xconcurrentio", &tail)) { FLAG_SET_CMDLINE(bool, UseLWPSynchronization, true); @@ -2957,13 +2949,6 @@ FLAG_SET_CMDLINE(bool, UseTLAB, true); } else if (match_option(option, "-XX:-UseTLE", &tail)) { FLAG_SET_CMDLINE(bool, UseTLAB, false); -SOLARIS_ONLY( - } else if (match_option(option, "-XX:+UsePermISM", &tail)) { - warning("-XX:+UsePermISM is obsolete."); - FLAG_SET_CMDLINE(bool, UseISM, true); - } else if (match_option(option, "-XX:-UsePermISM", &tail)) { - FLAG_SET_CMDLINE(bool, UseISM, false); -) } else if (match_option(option, "-XX:+DisplayVMOutputToStderr", &tail)) { FLAG_SET_CMDLINE(bool, DisplayVMOutputToStdout, false); FLAG_SET_CMDLINE(bool, DisplayVMOutputToStderr, true); @@ -3136,8 +3121,6 @@ // Note that large pages are enabled/disabled for both the // Java heap and the code cache. FLAG_SET_DEFAULT(UseLargePages, false); - SOLARIS_ONLY(FLAG_SET_DEFAULT(UseMPSS, false)); - SOLARIS_ONLY(FLAG_SET_DEFAULT(UseISM, false)); } // Tiered compilation is undefined with C1. diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/arguments.hpp --- a/src/share/vm/runtime/arguments.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/arguments.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -262,7 +262,6 @@ // Option flags static bool _has_profile; - static bool _has_alloc_profile; static const char* _gc_log_filename; static uintx _min_heap_size; @@ -464,9 +463,8 @@ // -Xloggc:, if not specified will be NULL static const char* gc_log_filename() { return _gc_log_filename; } - // -Xprof/-Xaprof + // -Xprof static bool has_profile() { return _has_profile; } - static bool has_alloc_profile() { return _has_alloc_profile; } // -Xms, -Xmx static uintx min_heap_size() { return _min_heap_size; } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/globals.hpp --- a/src/share/vm/runtime/globals.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/globals.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -175,6 +175,7 @@ define_pd_global(intx, ReservedCodeCacheSize, 32*M); define_pd_global(intx, CodeCacheExpansionSize, 32*K); define_pd_global(intx, CodeCacheMinBlockLength, 1); +define_pd_global(intx, CodeCacheMinimumUseSpace, 200*K); define_pd_global(uintx,MetaspaceSize, ScaleForWordSize(4*M)); define_pd_global(bool, NeverActAsServerClassMachine, true); define_pd_global(uint64_t,MaxRAM, 1ULL*G); @@ -3679,6 +3680,9 @@ develop(bool, VerifyGenericSignatures, false, \ "Abort VM on erroneous or inconsistent generic signatures") \ \ + product(bool, ParseGenericDefaults, false, \ + "Parse generic signatures for default method handling") \ + \ product(bool, UseVMInterruptibleIO, false, \ "(Unstable, Solaris-specific) Thread interrupt before or with " \ "EINTR for I/O operations results in OS_INTRPT. The default value"\ diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/handles.hpp --- a/src/share/vm/runtime/handles.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/handles.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -227,7 +227,7 @@ HandleArea* _prev; // link to outer (older) area public: // Constructor - HandleArea(HandleArea* prev) { + HandleArea(HandleArea* prev) : Arena(Chunk::tiny_size) { debug_only(_handle_mark_nesting = 0); debug_only(_no_handle_mark_nesting = 0); _prev = prev; diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/java.cpp --- a/src/share/vm/runtime/java.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/java.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -42,7 +42,6 @@ #include "oops/oop.inline.hpp" #include "oops/symbol.hpp" #include "prims/jvmtiExport.hpp" -#include "runtime/aprofiler.hpp" #include "runtime/arguments.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/compilationPolicy.hpp" @@ -509,16 +508,6 @@ } } - - if (Arguments::has_alloc_profile()) { - HandleMark hm; - // Do one last collection to enumerate all the objects - // allocated since the last one. - Universe::heap()->collect(GCCause::_allocation_profiler); - AllocationProfiler::disengage(); - AllocationProfiler::print(0); - } - if (PrintBytecodeHistogram) { BytecodeHistogram::print(); } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/os.hpp --- a/src/share/vm/runtime/os.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/os.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -507,16 +507,16 @@ // Symbol lookup, find nearest function name; basically it implements // dladdr() for all platforms. Name of the nearest function is copied - // to buf. Distance from its base address is returned as offset. + // to buf. Distance from its base address is optionally returned as offset. // If function name is not found, buf[0] is set to '\0' and offset is - // set to -1. + // set to -1 (if offset is non-NULL). static bool dll_address_to_function_name(address addr, char* buf, int buflen, int* offset); // Locate DLL/DSO. On success, full path of the library is copied to - // buf, and offset is set to be the distance between addr and the - // library's base address. On failure, buf[0] is set to '\0' and - // offset is set to -1. + // buf, and offset is optionally set to be the distance between addr + // and the library's base address. On failure, buf[0] is set to '\0' + // and offset is set to -1 (if offset is non-NULL). static bool dll_address_to_library_name(address addr, char* buf, int buflen, int* offset); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/thread.cpp --- a/src/share/vm/runtime/thread.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/thread.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -45,7 +45,6 @@ #include "prims/jvmtiExport.hpp" #include "prims/jvmtiThreadState.hpp" #include "prims/privilegedStack.hpp" -#include "runtime/aprofiler.hpp" #include "runtime/arguments.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/deoptimization.hpp" @@ -3677,7 +3676,6 @@ } if (Arguments::has_profile()) FlatProfiler::engage(main_thread, true); - if (Arguments::has_alloc_profile()) AllocationProfiler::engage(); if (MemProfiling) MemProfiler::engage(); StatSampler::engage(); if (CheckJNICalls) JniPeriodicChecker::engage(); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/runtime/vmStructs.cpp --- a/src/share/vm/runtime/vmStructs.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/runtime/vmStructs.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -263,7 +263,7 @@ unchecked_c2_static_field) \ \ /******************************************************************/ \ - /* OopDesc and Klass hierarchies (NOTE: MethodData* incomplete) */ \ + /* OopDesc and Klass hierarchies (NOTE: MethodData* incomplete) */ \ /******************************************************************/ \ \ volatile_nonstatic_field(oopDesc, _mark, markOop) \ @@ -274,21 +274,20 @@ volatile_nonstatic_field(ArrayKlass, _higher_dimension, Klass*) \ volatile_nonstatic_field(ArrayKlass, _lower_dimension, Klass*) \ nonstatic_field(ArrayKlass, _vtable_len, int) \ - nonstatic_field(ArrayKlass, _alloc_size, juint) \ nonstatic_field(ArrayKlass, _component_mirror, oop) \ - nonstatic_field(CompiledICHolder, _holder_method, Method*) \ + nonstatic_field(CompiledICHolder, _holder_method, Method*) \ nonstatic_field(CompiledICHolder, _holder_klass, Klass*) \ nonstatic_field(ConstantPool, _tags, Array*) \ - nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \ + nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \ nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \ nonstatic_field(ConstantPool, _operands, Array*) \ nonstatic_field(ConstantPool, _length, int) \ nonstatic_field(ConstantPool, _resolved_references, jobject) \ nonstatic_field(ConstantPool, _reference_map, Array*) \ nonstatic_field(ConstantPoolCache, _length, int) \ - nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \ + nonstatic_field(ConstantPoolCache, _constant_pool, ConstantPool*) \ nonstatic_field(InstanceKlass, _array_klasses, Klass*) \ - nonstatic_field(InstanceKlass, _methods, Array*) \ + nonstatic_field(InstanceKlass, _methods, Array*) \ nonstatic_field(InstanceKlass, _local_interfaces, Array*) \ nonstatic_field(InstanceKlass, _transitive_interfaces, Array*) \ nonstatic_field(InstanceKlass, _fields, Array*) \ @@ -336,9 +335,8 @@ nonstatic_field(Klass, _access_flags, AccessFlags) \ nonstatic_field(Klass, _subklass, Klass*) \ nonstatic_field(Klass, _next_sibling, Klass*) \ - nonstatic_field(Klass, _alloc_count, juint) \ nonstatic_field(MethodData, _size, int) \ - nonstatic_field(MethodData, _method, Method*) \ + nonstatic_field(MethodData, _method, Method*) \ nonstatic_field(MethodData, _data_size, int) \ nonstatic_field(MethodData, _data[0], intptr_t) \ nonstatic_field(MethodData, _nof_decompiles, uint) \ diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/services/memBaseline.cpp --- a/src/share/vm/services/memBaseline.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/services/memBaseline.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -486,7 +486,7 @@ const MemPointerRecord* mp1 = (const MemPointerRecord*)p1; const MemPointerRecord* mp2 = (const MemPointerRecord*)p2; int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr()); - assert(delta != 0, "dup pointer"); + assert(p1 == p2 || delta != 0, "dup pointer"); return delta; } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/services/memTracker.hpp --- a/src/share/vm/services/memTracker.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/services/memTracker.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -470,7 +470,21 @@ static void check_NMT_load(Thread* thr) { assert(thr != NULL, "Sanity check"); if (_slowdown_calling_thread && thr != _worker_thread) { +#ifdef _WINDOWS + // On Windows, os::NakedYield() does not work as well + // as os::yield_all() os::yield_all(); +#else + // On Solaris, os::yield_all() depends on os::sleep() + // which requires JavaTherad in _thread_in_vm state. + // Transits thread to _thread_in_vm state can be dangerous + // if caller holds lock, as it may deadlock with Threads_lock. + // So use NaKedYield instead. + // + // Linux and BSD, NakedYield() and yield_all() implementations + // are the same. + os::NakedYield(); +#endif } } diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/utilities/debug.cpp --- a/src/share/vm/utilities/debug.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/utilities/debug.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -314,8 +314,8 @@ #ifndef PRODUCT #include -void test_error_handler(size_t test_num) -{ +void test_error_handler() { + uintx test_num = ErrorHandlerTest; if (test_num == 0) return; // If asserts are disabled, use the corresponding guarantee instead. @@ -327,6 +327,8 @@ const char* const eol = os::line_separator(); const char* const msg = "this message should be truncated during formatting"; + char * const dataPtr = NULL; // bad data pointer + const void (*funcPtr)(void) = (const void(*)()) 0xF; // bad function pointer // Keep this in sync with test/runtime/6888954/vmerrors.sh. switch (n) { @@ -348,11 +350,16 @@ case 9: ShouldNotCallThis(); case 10: ShouldNotReachHere(); case 11: Unimplemented(); - // This is last because it does not generate an hs_err* file on Windows. - case 12: os::signal_raise(SIGSEGV); + // There's no guarantee the bad data pointer will crash us + // so "break" out to the ShouldNotReachHere(). + case 12: *dataPtr = '\0'; break; + // There's no guarantee the bad function pointer will crash us + // so "break" out to the ShouldNotReachHere(). + case 13: (*funcPtr)(); break; - default: ShouldNotReachHere(); + default: tty->print_cr("ERROR: %d: unexpected test_num value.", n); } + ShouldNotReachHere(); } #endif // !PRODUCT diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/utilities/debug.hpp --- a/src/share/vm/utilities/debug.hpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/utilities/debug.hpp Fri Jul 12 16:53:39 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -243,7 +243,7 @@ void set_error_reported(); /* Test assert(), fatal(), guarantee(), etc. */ -NOT_PRODUCT(void test_error_handler(size_t test_num);) +NOT_PRODUCT(void test_error_handler();) void pd_ps(frame f); void pd_obfuscate_location(char *buf, size_t buflen); diff -r 1a3390aa8326 -r 2b9946e10587 src/share/vm/utilities/vmError.cpp --- a/src/share/vm/utilities/vmError.cpp Thu Jul 11 10:13:37 2013 -0700 +++ b/src/share/vm/utilities/vmError.cpp Fri Jul 12 16:53:39 2013 -0700 @@ -908,10 +908,11 @@ // This is not the first error, see if it happened in a different thread // or in the same thread during error reporting. if (first_error_tid != mytid) { - jio_snprintf(buffer, sizeof(buffer), + char msgbuf[64]; + jio_snprintf(msgbuf, sizeof(msgbuf), "[thread " INT64_FORMAT " also had an error]", mytid); - out.print_raw_cr(buffer); + out.print_raw_cr(msgbuf); // error reporting is not MT-safe, block current thread os::infinite_sleep(); diff -r 1a3390aa8326 -r 2b9946e10587 test/compiler/8005956/PolynomialRoot.java --- a/test/compiler/8005956/PolynomialRoot.java Thu Jul 11 10:13:37 2013 -0700 +++ b/test/compiler/8005956/PolynomialRoot.java Fri Jul 12 16:53:39 2013 -0700 @@ -15,7 +15,7 @@ * @bug 8005956 * @summary C2: assert(!def_outside->member(r)) failed: Use of external LRG overlaps the same LRG defined in this block * -* @run main PolynomialRoot +* @run main/timeout=300 PolynomialRoot */ public class PolynomialRoot { @@ -757,19 +757,26 @@ public static void main(final String [] args) { - final long t0=System.currentTimeMillis(); - final double eps=1e-6; - //checkRoots(); - final java.util.Random r=new java.util.Random(-1381923); - printSpecialValues(); + if (System.getProperty("os.arch").equals("x86") || + System.getProperty("os.arch").equals("amd64") || + System.getProperty("os.arch").equals("x86_64")){ + final long t0=System.currentTimeMillis(); + final double eps=1e-6; + //checkRoots(); + final java.util.Random r=new java.util.Random(-1381923); + printSpecialValues(); - final int n_tests=10000000; - //testRoots(2,n_tests,r,eps); - //testRoots(3,n_tests,r,eps); - testRoots(4,n_tests,r,eps); - final long t1=System.currentTimeMillis(); - System.err.println("PolynomialRoot.main: "+n_tests+" tests OK done in "+(t1-t0)+" milliseconds. ver=$Id: PolynomialRoot.java,v 1.105 2012/08/18 00:00:05 mal Exp $"); - } + final int n_tests=100000; + //testRoots(2,n_tests,r,eps); + //testRoots(3,n_tests,r,eps); + testRoots(4,n_tests,r,eps); + final long t1=System.currentTimeMillis(); + System.err.println("PolynomialRoot.main: "+n_tests+" tests OK done in "+(t1-t0)+" milliseconds. ver=$Id: PolynomialRoot.java,v 1.105 2012/08/18 00:00:05 mal Exp $"); + System.out.println("PASSED"); + } else { + System.out.println("PASS test for non-x86"); + } + } diff -r 1a3390aa8326 -r 2b9946e10587 test/compiler/codecache/CheckUpperLimit.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/compiler/codecache/CheckUpperLimit.java Fri Jul 12 16:53:39 2013 -0700 @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8015635 + * @summary Test ensures that the ReservedCodeCacheSize is at most MAXINT + * @library /testlibrary + * + */ +import com.oracle.java.testlibrary.*; + +public class CheckUpperLimit { + public static void main(String[] args) throws Exception { + ProcessBuilder pb; + OutputAnalyzer out; + + pb = ProcessTools.createJavaProcessBuilder("-XX:ReservedCodeCacheSize=2048m", "-version"); + out = new OutputAnalyzer(pb.start()); + out.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ReservedCodeCacheSize=2049m", "-version"); + out = new OutputAnalyzer(pb.start()); + out.shouldContain("Invalid ReservedCodeCacheSize="); + out.shouldHaveExitValue(1); + } +} diff -r 1a3390aa8326 -r 2b9946e10587 test/runtime/6888954/vmerrors.sh --- a/test/runtime/6888954/vmerrors.sh Thu Jul 11 10:13:37 2013 -0700 +++ b/test/runtime/6888954/vmerrors.sh Fri Jul 12 16:53:39 2013 -0700 @@ -1,5 +1,6 @@ # @test # @bug 6888954 +# @bug 8015884 # @summary exercise HotSpot error handling code # @author John Coomes # @run shell vmerrors.sh @@ -27,9 +28,24 @@ rc=0 assert_re='(assert|guarantee)[(](str|num).*failed: *' +# for bad_data_ptr_re: +# EXCEPTION_ACCESS_VIOLATION - Win-* +# SIGILL - MacOS X +# SIGSEGV - Linux-*, Solaris SPARC-*, Solaris X86-* +# +bad_data_ptr_re='(SIGILL|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc=' +# +# for bad_func_ptr_re: +# EXCEPTION_ACCESS_VIOLATION - Win-* +# SIGBUS - Solaris SPARC-64 +# SIGSEGV - Linux-*, Solaris SPARC-32, Solaris X86-* +# +# Note: would like to use "pc=0x00*0f," in the pattern, but Solaris SPARC-* +# gets its signal at a PC in test_error_handler(). +# +bad_func_ptr_re='(SIGBUS|SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc=' guarantee_re='guarantee[(](str|num).*failed: *' fatal_re='fatal error: *' -signal_re='(SIGSEGV|EXCEPTION_ACCESS_VIOLATION).* at pc=' tail_1='.*expected null' tail_2='.*num=' @@ -39,8 +55,9 @@ "${fatal_re}${tail_1}" "${fatal_re}${tail_2}" \ "${fatal_re}.*truncated" "ChunkPool::allocate" \ "ShouldNotCall" "ShouldNotReachHere" \ - "Unimplemented" "$signal_re" - + "Unimplemented" "$bad_data_ptr_re" \ + "$bad_func_ptr_re" + do i2=$i [ $i -lt 10 ] && i2=0$i