--- a/.hgtags-top-repo Tue Jul 16 15:16:24 2013 -0700
+++ b/.hgtags-top-repo Wed Jul 05 19:03:35 2017 +0200
@@ -219,3 +219,4 @@
785d07fe38901ecc1b7e0145e53e1c3da9361fee jdk8-b95
c156084add486f941c12d886a0b1b2854795d557 jdk8-b96
a1c1e8bf71f354f3aec0214cf13d6668811e021d jdk8-b97
+0d0c983a817bbe8518a5ff201306334a8de267f2 jdk8-b98
--- a/hotspot/.hgtags Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/.hgtags Wed Jul 05 19:03:35 2017 +0200
@@ -357,3 +357,5 @@
2b9380b0bf0b649f40704735773e8956c2d88ba0 hs25-b39
d197d377ab2e016d024e8c86cb06a57bd7eae590 jdk8-b97
c9dd82da51ed34a28f7c6b3245163ee962e94572 hs25-b40
+30b5b75c42ac5174b640fbef8aa87527668e8400 jdk8-b98
+2b9946e10587f74ef75ae8145bea484df4a2738b hs25-b41
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/ArrayKlass.java Wed Jul 05 19:03:35 2017 +0200
@@ -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);
}
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/Klass.java Wed Jul 05 19:03:35 2017 +0200
@@ -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() {
--- a/hotspot/make/bsd/makefiles/mapfile-vers-debug Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-debug Wed Jul 05 19:03:35 2017 +0200
@@ -221,7 +221,6 @@
_JVM_SetLength
_JVM_SetNativeThreadName
_JVM_SetPrimitiveArrayElement
- _JVM_SetProtectionDomain
_JVM_SetSockOpt
_JVM_SetThreadPriority
_JVM_Sleep
--- a/hotspot/make/bsd/makefiles/mapfile-vers-product Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/make/bsd/makefiles/mapfile-vers-product Wed Jul 05 19:03:35 2017 +0200
@@ -221,7 +221,6 @@
_JVM_SetLength
_JVM_SetNativeThreadName
_JVM_SetPrimitiveArrayElement
- _JVM_SetProtectionDomain
_JVM_SetSockOpt
_JVM_SetThreadPriority
_JVM_Sleep
--- a/hotspot/make/hotspot_version Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/make/hotspot_version Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- a/hotspot/make/linux/makefiles/mapfile-vers-debug Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/make/linux/makefiles/mapfile-vers-debug Wed Jul 05 19:03:35 2017 +0200
@@ -223,7 +223,6 @@
JVM_SetLength;
JVM_SetNativeThreadName;
JVM_SetPrimitiveArrayElement;
- JVM_SetProtectionDomain;
JVM_SetSockOpt;
JVM_SetThreadPriority;
JVM_Sleep;
--- a/hotspot/make/linux/makefiles/mapfile-vers-product Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/make/linux/makefiles/mapfile-vers-product Wed Jul 05 19:03:35 2017 +0200
@@ -223,7 +223,6 @@
JVM_SetLength;
JVM_SetNativeThreadName;
JVM_SetPrimitiveArrayElement;
- JVM_SetProtectionDomain;
JVM_SetSockOpt;
JVM_SetThreadPriority;
JVM_Sleep;
--- a/hotspot/make/solaris/makefiles/mapfile-vers Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/make/solaris/makefiles/mapfile-vers Wed Jul 05 19:03:35 2017 +0200
@@ -223,7 +223,6 @@
JVM_SetLength;
JVM_SetNativeThreadName;
JVM_SetPrimitiveArrayElement;
- JVM_SetProtectionDomain;
JVM_SetSockOpt;
JVM_SetThreadPriority;
JVM_Sleep;
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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("<offset %#x>", addr - (intptr_t)dlinfo.dli_fbase);
} else {
st->print("<absolute address>");
}
- 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);
--- a/hotspot/src/os/linux/vm/os_linux.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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("<offset %#x>", addr - (intptr_t)dlinfo.dli_fbase);
} else {
st->print("<absolute address>");
}
- 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);
--- a/hotspot/src/os/solaris/vm/globals_solaris.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/solaris/vm/globals_solaris.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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")
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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("<offset %#lx>", addr-(intptr_t)dlinfo.dli_fbase);
else
st->print("<absolute address>");
- 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);
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- a/hotspot/src/os/windows/vm/os_windows.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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(); }
--- a/hotspot/src/os/windows/vm/os_windows.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
};
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/adlc/forms.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/adlc/forms.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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");
--- a/hotspot/src/share/vm/classfile/defaultMethods.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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<Pair<Method*,QualifiedState> > _members;
ResourceHashtable<Method*, int> _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<StatefulMethodFamily*> _methods;
+ GrowableArray<StatefulGenericMethodFamily*> _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<MethodFamily*>* array) {
+ void extract_families_into(GrowableArray<GenericMethodFamily*>* 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<FindMethodsByErasedSig> {
+ 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<FindMethodsByName> {
+class FindMethodsByGenericSig : public HierarchyVisitor<FindMethodsByGenericSig> {
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<MethodFamily*>* methods) {
+ void get_discovered_families(GrowableArray<GenericMethodFamily*>* 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<MethodFamily*>* methods, Symbol* match) {
+static void print_generic_families(
+ GrowableArray<GenericMethodFamily*>* 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("<Matching>");
} else {
tty->print_cr("<Non-Matching>");
}
- lm->print_on(tty, 1);
+ lm->print_sig_on(tty, lm->get_generic_sig(), 1);
}
}
#endif // ndef PRODUCT
+static void create_overpasses(
+ GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
+
+static void generate_generic_defaults(
+ InstanceKlass* klass, GrowableArray<EmptyVtableSlot*>* 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<GenericMethodFamily*> 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<EmptyVtableSlot*>* 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<Method*>* new_methods, TRAPS);
-static void create_overpasses(
- GrowableArray<EmptyVtableSlot*>* 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<MethodFamily*> 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<ShadowChecker> {
- 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<MethodFamily*> 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<GenericMethodFamily*> 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<address>(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<address>(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);
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -234,6 +234,7 @@
static GrowableArray<Klass*>* _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);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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;
}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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() {
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
}
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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"
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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();
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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 {
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/memory/allocation.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/allocation.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
}
}
--- a/hotspot/src/share/vm/memory/allocation.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/allocation.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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?");
}
--- a/hotspot/src/share/vm/memory/defNewGeneration.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -252,7 +252,6 @@
// Iteration
void object_iterate(ObjectClosure* blk);
- void object_iterate_since_last_GC(ObjectClosure* cl);
void younger_refs_iterate(OopsInGenClosure* cl);
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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.
--- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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,
--- a/hotspot/src/share/vm/memory/generation.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/generation.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/memory/generation.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/generation.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/memory/heapInspection.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/heapInspection.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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<mtInternal> {
private:
KlassInfoEntry* _list;
--- a/hotspot/src/share/vm/memory/klassInfoClosure.hpp Tue Jul 16 15:16:24 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
--- a/hotspot/src/share/vm/memory/sharedHeap.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/sharedHeap.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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;
--- a/hotspot/src/share/vm/memory/universe.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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"
--- a/hotspot/src/share/vm/oops/arrayKlass.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/oops/arrayKlass.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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) {
--- a/hotspot/src/share/vm/oops/arrayKlass.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/oops/arrayKlass.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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<Method*>* methods, Symbol* name, Symbol* signature) {
int len = methods->length();
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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());
--- a/hotspot/src/share/vm/oops/klass.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/oops/klass.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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 {
--- a/hotspot/src/share/vm/oops/klass.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/oops/klass.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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.
--- a/hotspot/src/share/vm/prims/jni.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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;
}
--- a/hotspot/src/share/vm/prims/jvm.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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.
--- a/hotspot/src/share/vm/prims/jvm.h Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/prims/jvm.h Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/runtime/aprofiler.cpp Tue Jul 16 15:16:24 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<Klass*>* 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<Klass*>(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.
-}
--- a/hotspot/src/share/vm/runtime/aprofiler.hpp Tue Jul 16 15:16:24 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<Klass*>* _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
--- a/hotspot/src/share/vm/runtime/arguments.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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.
--- a/hotspot/src/share/vm/runtime/arguments.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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:<file>, 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; }
--- a/hotspot/src/share/vm/runtime/globals.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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"\
--- a/hotspot/src/share/vm/runtime/handles.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/handles.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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;
--- a/hotspot/src/share/vm/runtime/java.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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();
}
--- a/hotspot/src/share/vm/runtime/os.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/runtime/thread.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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();
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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<u1>*) \
- nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \
+ nonstatic_field(ConstantPool, _cache, ConstantPoolCache*) \
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
nonstatic_field(ConstantPool, _length, int) \
nonstatic_field(ConstantPool, _resolved_references, jobject) \
nonstatic_field(ConstantPool, _reference_map, Array<u2>*) \
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<Method*>*) \
+ nonstatic_field(InstanceKlass, _methods, Array<Method*>*) \
nonstatic_field(InstanceKlass, _local_interfaces, Array<Klass*>*) \
nonstatic_field(InstanceKlass, _transitive_interfaces, Array<Klass*>*) \
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
@@ -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) \
--- a/hotspot/src/share/vm/services/memBaseline.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/services/memBaseline.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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;
}
--- a/hotspot/src/share/vm/services/memTracker.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/services/memTracker.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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
}
}
--- a/hotspot/src/share/vm/utilities/debug.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/utilities/debug.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -314,8 +314,8 @@
#ifndef PRODUCT
#include <signal.h>
-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
--- a/hotspot/src/share/vm/utilities/debug.hpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/utilities/debug.hpp Wed Jul 05 19:03:35 2017 +0200
@@ -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);
--- a/hotspot/src/share/vm/utilities/vmError.cpp Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Wed Jul 05 19:03:35 2017 +0200
@@ -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();
--- a/hotspot/test/compiler/8005956/PolynomialRoot.java Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/test/compiler/8005956/PolynomialRoot.java Wed Jul 05 19:03:35 2017 +0200
@@ -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");
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/codecache/CheckUpperLimit.java Wed Jul 05 19:03:35 2017 +0200
@@ -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);
+ }
+}
--- a/hotspot/test/runtime/6888954/vmerrors.sh Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/test/runtime/6888954/vmerrors.sh Wed Jul 05 19:03:35 2017 +0200
@@ -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
--- a/hotspot/test/runtime/8001071/Test8001071.sh Tue Jul 16 15:16:24 2013 -0700
+++ b/hotspot/test/runtime/8001071/Test8001071.sh Wed Jul 05 19:03:35 2017 +0200
@@ -2,21 +2,21 @@
# 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.