--- a/.hgtags-top-repo Thu Jul 12 16:47:53 2012 -0700
+++ b/.hgtags-top-repo Wed Jul 05 18:16:35 2017 +0200
@@ -168,3 +168,4 @@
e4f81a817447c3a4f6868f083c81c2fb1b15d44c jdk8-b44
633f2378c904c92bb922a6e19e9f62fe8eac14af jdk8-b45
27fa766a2298ba8347dc198f0cf85ba6618e17db jdk8-b46
+1dcb4b7b9373e64e135c12fe1f8699f1f80e51e8 jdk8-b47
--- a/hotspot/.hgtags Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/.hgtags Wed Jul 05 18:16:35 2017 +0200
@@ -259,3 +259,5 @@
9d5f20961bc5846fa8d098d534effafbbdae0a58 jdk8-b45
40e5a3f2907ed02b335c7caa8ecf068cc801380d hs24-b15
cf37a594c38db2ea926954154636f9f81da2e032 jdk8-b46
+0c7bb1f4f9c8062b5c5bfa56b3bdca44839b4109 jdk8-b47
+66b0450071c1534e014b131892cc86b63f1d009c hs24-b16
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/jdi/ReferenceTypeImpl.java Wed Jul 05 18:16:35 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -688,8 +688,7 @@
if (sde == null) {
String extension = null;
if (saKlass instanceof InstanceKlass) {
- Symbol sdeSym = ((InstanceKlass)saKlass).getSourceDebugExtension();
- extension = (sdeSym != null)? sdeSym.asString() : null;
+ extension = ((InstanceKlass)saKlass).getSourceDebugExtension();
}
if (extension == null) {
sde = NO_SDE_INFO_MARK;
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java Wed Jul 05 18:16:35 2017 +0200
@@ -342,7 +342,7 @@
public Oop getProtectionDomain() { return protectionDomain.getValue(this); }
public ObjArray getSigners() { return (ObjArray) signers.getValue(this); }
public Symbol getSourceFileName() { return getSymbol(sourceFileName); }
- public Symbol getSourceDebugExtension(){ return getSymbol(sourceDebugExtension); }
+ public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getHandle())); }
public TypeArray getInnerClasses() { return (TypeArray) innerClasses.getValue(this); }
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/BasicHashtable.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/BasicHashtable.java Wed Jul 05 18:16:35 2017 +0200
@@ -41,10 +41,10 @@
}
private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("BasicHashtable");
+ Type type = db.lookupType("BasicHashtable<mtInternal>");
tableSizeField = type.getCIntegerField("_table_size");
bucketsField = type.getAddressField("_buckets");
- bucketSize = db.lookupType("HashtableBucket").getSize();
+ bucketSize = db.lookupType("HashtableBucket<mtInternal>").getSize();
}
// Fields
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/BasicHashtableEntry.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/BasicHashtableEntry.java Wed Jul 05 18:16:35 2017 +0200
@@ -41,7 +41,7 @@
}
private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("BasicHashtableEntry");
+ Type type = db.lookupType("BasicHashtableEntry<mtInternal>");
hashField = type.getCIntegerField("_hash");
nextField = type.getAddressField("_next");
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/Hashtable.java Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
private static synchronized void initialize(TypeDataBase db) {
// just to confirm that type exists
- Type type = db.lookupType("Hashtable<intptr_t>");
+ Type type = db.lookupType("IntptrHashtable");
}
// derived class may return Class<? extends HashtableEntry>
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableBucket.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableBucket.java Wed Jul 05 18:16:35 2017 +0200
@@ -39,7 +39,7 @@
}
private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("HashtableBucket");
+ Type type = db.lookupType("HashtableBucket<mtInternal>");
entryField = type.getAddressField("_entry");
}
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableEntry.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/utilities/HashtableEntry.java Wed Jul 05 18:16:35 2017 +0200
@@ -41,7 +41,7 @@
}
private static synchronized void initialize(TypeDataBase db) {
- Type type = db.lookupType("HashtableEntry<intptr_t>");
+ Type type = db.lookupType("IntptrHashtableEntry");
literalField = type.getAddressField("_literal");
}
--- a/hotspot/make/bsd/makefiles/jvmg.make Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/make/bsd/makefiles/jvmg.make Wed Jul 05 18:16:35 2017 +0200
@@ -27,7 +27,9 @@
# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS)
DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
-CFLAGS += $(DEBUG_CFLAGS/BYFILE)
+
+# _NMT_NOINLINE_ informs NMT that no inlining by Compiler
+CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_
# Set the environment variable HOTSPARC_GENERIC to "true"
# to inhibit the effect of the previous line on CFLAGS.
--- a/hotspot/make/hotspot_version Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/make/hotspot_version Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
HS_MAJOR_VER=24
HS_MINOR_VER=0
-HS_BUILD_NUMBER=15
+HS_BUILD_NUMBER=16
JDK_MAJOR_VER=1
JDK_MINOR_VER=8
--- a/hotspot/make/linux/makefiles/jvmg.make Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/make/linux/makefiles/jvmg.make Wed Jul 05 18:16:35 2017 +0200
@@ -1,5 +1,5 @@
#
-# Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 1999, 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
@@ -27,7 +27,9 @@
# Compiler specific DEBUG_CFLAGS are passed in from gcc.make, sparcWorks.make
DEBUG_CFLAGS/DEFAULT= $(DEBUG_CFLAGS)
DEBUG_CFLAGS/BYFILE = $(DEBUG_CFLAGS/$@)$(DEBUG_CFLAGS/DEFAULT$(DEBUG_CFLAGS/$@))
-CFLAGS += $(DEBUG_CFLAGS/BYFILE)
+
+# _NMT_NOINLINE_ informs NMT that no inlining by Compiler
+CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_
# Set the environment variable HOTSPARC_GENERIC to "true"
# to inhibit the effect of the previous line on CFLAGS.
--- a/hotspot/make/solaris/makefiles/jvmg.make Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/make/solaris/makefiles/jvmg.make Wed Jul 05 18:16:35 2017 +0200
@@ -37,7 +37,8 @@
endif
endif
-CFLAGS += $(DEBUG_CFLAGS/BYFILE)
+# _NMT_NOINLINE_ informs NMT that no inlining by Compiler
+CFLAGS += $(DEBUG_CFLAGS/BYFILE) -D_NMT_NOINLINE_
# Set the environment variable HOTSPARC_GENERIC to "true"
# to inhibit the effect of the previous line on CFLAGS.
--- a/hotspot/make/windows/makefiles/debug.make Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/make/windows/makefiles/debug.make Wed Jul 05 18:16:35 2017 +0200
@@ -38,7 +38,8 @@
!include ../local.make
!include compile.make
-CXX_FLAGS=$(CXX_FLAGS) $(DEBUG_OPT_OPTION)
+# _NMT_NOINLINE_ informs NMT that no inlining by Compiler
+CXX_FLAGS=$(CXX_FLAGS) $(DEBUG_OPT_OPTION) /D "_NMT_NOINLINE_"
!include $(WorkSpace)/make/windows/makefiles/vm.make
!include local.make
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -440,7 +440,7 @@
// code needs to be changed accordingly.
// The next few definitions allow the code to be verbatim:
-#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n))
+#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
#define getenv(n) ::getenv(n)
/*
@@ -1913,11 +1913,11 @@
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
- FREE_C_HEAP_ARRAY(char, pelements[i]);
+ FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal);
}
}
if (pelements != NULL) {
- FREE_C_HEAP_ARRAY(char*, pelements);
+ FREE_C_HEAP_ARRAY(char*, pelements, mtInternal);
}
} else {
snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname);
@@ -2766,7 +2766,7 @@
// All it does is to check if there are enough free pages
// left at the time of mmap(). This could be a potential
// problem.
-bool os::commit_memory(char* addr, size_t size, bool exec) {
+bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
#ifdef __OpenBSD__
// XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
@@ -2790,7 +2790,7 @@
#endif
#endif
-bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
+bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
bool exec) {
#ifndef _ALLBSD_SOURCE
if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
@@ -2806,7 +2806,7 @@
return commit_memory(addr, size, exec);
}
-void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
+void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
#ifndef _ALLBSD_SOURCE
if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
// We don't check the return value: madvise(MADV_HUGEPAGE) may not
@@ -2816,7 +2816,7 @@
#endif
}
-void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) {
+void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
::madvise(addr, bytes, MADV_DONTNEED);
}
@@ -2958,7 +2958,7 @@
unsigned long* os::Bsd::_numa_all_nodes;
#endif
-bool os::uncommit_memory(char* addr, size_t size) {
+bool os::pd_uncommit_memory(char* addr, size_t size) {
#ifdef __OpenBSD__
// XXX: Work-around mmap/MAP_FIXED bug temporarily on OpenBSD
return ::mprotect(addr, size, PROT_NONE) == 0;
@@ -2969,7 +2969,7 @@
#endif
}
-bool os::create_stack_guard_pages(char* addr, size_t size) {
+bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
return os::commit_memory(addr, size);
}
@@ -3023,12 +3023,12 @@
return ::munmap(addr, size) == 0;
}
-char* os::reserve_memory(size_t bytes, char* requested_addr,
+char* os::pd_reserve_memory(size_t bytes, char* requested_addr,
size_t alignment_hint) {
return anon_mmap(requested_addr, bytes, (requested_addr != NULL));
}
-bool os::release_memory(char* addr, size_t size) {
+bool os::pd_release_memory(char* addr, size_t size) {
return anon_munmap(addr, size);
}
@@ -3331,7 +3331,7 @@
// Reserve memory at an arbitrary address, only if that area is
// available (and not reserved for something else).
-char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
const int max_tries = 10;
char* base[max_tries];
size_t size[max_tries];
@@ -4987,7 +4987,7 @@
}
// Map a block of memory.
-char* os::map_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
int prot;
@@ -5019,7 +5019,7 @@
// Remap a block of memory.
-char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
// same as map_memory() on this OS
@@ -5029,7 +5029,7 @@
// Unmap a block of memory.
-bool os::unmap_memory(char* addr, size_t bytes) {
+bool os::pd_unmap_memory(char* addr, size_t bytes) {
return munmap(addr, bytes) == 0;
}
@@ -5801,3 +5801,14 @@
return true;
}
+
+// Get the default path to the core file
+// Returns the length of the string
+int os::get_core_path(char* buffer, size_t bufferSize) {
+ int n = jio_snprintf(buffer, bufferSize, "/cores");
+
+ // Truncate if theoretical string was longer than bufferSize
+ n = MIN2(n, (int)bufferSize);
+
+ return n;
+}
--- a/hotspot/src/os/bsd/vm/os_bsd.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -312,7 +312,7 @@
};
-class PlatformEvent : public CHeapObj {
+class PlatformEvent : public CHeapObj<mtInternal> {
private:
double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line
volatile int _Event ;
@@ -347,7 +347,7 @@
void SetAssociation (Thread * a) { _Assoc = a ; }
} ;
-class PlatformParker : public CHeapObj {
+class PlatformParker : public CHeapObj<mtInternal> {
protected:
pthread_mutex_t _mutex [1] ;
pthread_cond_t _cond [1] ;
--- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -95,7 +95,7 @@
// On Bsd, reservations are made on a page by page basis, nothing to do.
-inline void os::split_reserved_memory(char *base, size_t size,
+inline void os::pd_split_reserved_memory(char *base, size_t size,
size_t split, bool realloc) {
}
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -126,7 +126,7 @@
}
}
}
- FREE_C_HEAP_ARRAY(char, destfile);
+ FREE_C_HEAP_ARRAY(char, destfile, mtInternal);
}
@@ -153,7 +153,7 @@
const char* tmpdir = os::get_temp_directory();
const char* perfdir = PERFDATA_NAME;
size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
- char* dirname = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
// construct the path name to user specific tmp directory
snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user);
@@ -246,7 +246,7 @@
if (bufsize == -1)
bufsize = 1024;
- char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize);
+ char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
// POSIX interface to getpwuid_r is used on LINUX
struct passwd* p;
@@ -278,14 +278,14 @@
"pw_name zero length");
}
}
- FREE_C_HEAP_ARRAY(char, pwbuf);
+ FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
return NULL;
}
- char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1);
+ char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal);
strcpy(user_name, p->pw_name);
- FREE_C_HEAP_ARRAY(char, pwbuf);
+ FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
return user_name;
}
@@ -328,7 +328,7 @@
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname));
+ char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
@@ -338,7 +338,7 @@
}
char* usrdir_name = NEW_C_HEAP_ARRAY(char,
- strlen(tmpdirname) + strlen(dentry->d_name) + 2);
+ strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);
strcpy(usrdir_name, tmpdirname);
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
@@ -346,7 +346,7 @@
DIR* subdirp = os::opendir(usrdir_name);
if (subdirp == NULL) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
continue;
}
@@ -357,13 +357,13 @@
// symlink can be exploited.
//
if (!is_directory_secure(usrdir_name)) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
os::closedir(subdirp);
continue;
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name));
+ char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
@@ -372,7 +372,7 @@
int result;
char* filename = NEW_C_HEAP_ARRAY(char,
- strlen(usrdir_name) + strlen(udentry->d_name) + 2);
+ strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal);
strcpy(filename, usrdir_name);
strcat(filename, "/");
@@ -381,13 +381,13 @@
// don't follow symbolic links for the file
RESTARTABLE(::lstat(filename, &statbuf), result);
if (result == OS_ERR) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
// skip over files that are not regular files.
if (!S_ISREG(statbuf.st_mode)) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
@@ -397,23 +397,23 @@
if (statbuf.st_ctime > oldest_ctime) {
char* user = strchr(dentry->d_name, '_') + 1;
- if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user);
- oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
+ if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user, mtInternal);
+ oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
strcpy(oldest_user, user);
oldest_ctime = statbuf.st_ctime;
}
}
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf);
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf);
+ FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(oldest_user);
}
@@ -434,7 +434,7 @@
// add 2 for the file separator and a null terminator.
size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
- char* name = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
snprintf(name, nbytes, "%s/%d", dirname, vmid);
return name;
@@ -472,7 +472,7 @@
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "/");
@@ -480,7 +480,7 @@
remove_file(path);
- FREE_C_HEAP_ARRAY(char, path);
+ FREE_C_HEAP_ARRAY(char, path, mtInternal);
}
@@ -517,7 +517,7 @@
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname));
+ char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -556,7 +556,7 @@
errno = 0;
}
os::closedir(dirp);
- FREE_C_HEAP_ARRAY(char, dbuf);
+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// make the user specific temporary directory. Returns true if
@@ -723,11 +723,11 @@
fd = create_sharedmem_resources(dirname, filename, size);
- FREE_C_HEAP_ARRAY(char, user_name);
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
if (fd == -1) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
return NULL;
}
@@ -743,7 +743,7 @@
warning("mmap failed - %s\n", strerror(errno));
}
remove_file(filename);
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
return NULL;
}
@@ -869,7 +869,7 @@
// store file, we don't follow them when attaching either.
//
if (!is_directory_secure(dirname)) {
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
@@ -884,9 +884,9 @@
strcpy(rfilename, filename);
// free the c heap resources that are no longer needed
- if (luser != user) FREE_C_HEAP_ARRAY(char, luser);
- FREE_C_HEAP_ARRAY(char, dirname);
- FREE_C_HEAP_ARRAY(char, filename);
+ if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
// open the shared memory file for the give vmid
fd = open_sharedmem_file(rfilename, file_flags, CHECK);
--- a/hotspot/src/os/linux/vm/os_linux.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -371,7 +371,7 @@
// code needs to be changed accordingly.
// The next few definitions allow the code to be verbatim:
-#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n))
+#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
#define getenv(n) ::getenv(n)
/*
@@ -639,7 +639,7 @@
size_t n = confstr(_CS_GNU_LIBC_VERSION, NULL, 0);
if (n > 0) {
- char *str = (char *)malloc(n);
+ char *str = (char *)malloc(n, mtInternal);
confstr(_CS_GNU_LIBC_VERSION, str, n);
os::Linux::set_glibc_version(str);
} else {
@@ -652,7 +652,7 @@
n = confstr(_CS_GNU_LIBPTHREAD_VERSION, NULL, 0);
if (n > 0) {
- char *str = (char *)malloc(n);
+ char *str = (char *)malloc(n, mtInternal);
confstr(_CS_GNU_LIBPTHREAD_VERSION, str, n);
// Vanilla RH-9 (glibc 2.3.2) has a bug that confstr() always tells
// us "NPTL-0.29" even we are running with LinuxThreads. Check if this
@@ -1685,11 +1685,11 @@
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
- FREE_C_HEAP_ARRAY(char, pelements[i]);
+ FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal);
}
}
if (pelements != NULL) {
- FREE_C_HEAP_ARRAY(char*, pelements);
+ FREE_C_HEAP_ARRAY(char*, pelements, mtInternal);
}
} else {
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
@@ -2469,7 +2469,7 @@
// All it does is to check if there are enough free pages
// left at the time of mmap(). This could be a potential
// problem.
-bool os::commit_memory(char* addr, size_t size, bool exec) {
+bool os::pd_commit_memory(char* addr, size_t size, bool exec) {
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
uintptr_t res = (uintptr_t) ::mmap(addr, size, prot,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
@@ -2492,7 +2492,7 @@
#define MADV_HUGEPAGE 14
#endif
-bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
+bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
bool exec) {
if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
@@ -2516,7 +2516,7 @@
return false;
}
-void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
+void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
if (UseHugeTLBFS && alignment_hint > (size_t)vm_page_size()) {
// We don't check the return value: madvise(MADV_HUGEPAGE) may not
// be supported or the memory may already be backed by huge pages.
@@ -2524,7 +2524,7 @@
}
}
-void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) {
+void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) {
// This method works by doing an mmap over an existing mmaping and effectively discarding
// the existing pages. However it won't work for SHM-based large pages that cannot be
// uncommitted at all. We don't do anything in this case to avoid creating a segment with
@@ -2646,7 +2646,7 @@
if (numa_available() != -1) {
set_numa_all_nodes((unsigned long*)libnuma_dlsym(handle, "numa_all_nodes"));
// Create a cpu -> node mapping
- _cpu_to_node = new (ResourceObj::C_HEAP) GrowableArray<int>(0, true);
+ _cpu_to_node = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<int>(0, true);
rebuild_cpu_to_node_map();
return true;
}
@@ -2676,7 +2676,7 @@
cpu_to_node()->at_grow(cpu_num - 1);
size_t node_num = numa_get_groups_num();
- unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size);
+ unsigned long *cpu_map = NEW_C_HEAP_ARRAY(unsigned long, cpu_map_size, mtInternal);
for (size_t i = 0; i < node_num; i++) {
if (numa_node_to_cpus(i, cpu_map, cpu_map_size * sizeof(unsigned long)) != -1) {
for (size_t j = 0; j < cpu_map_valid_size; j++) {
@@ -2690,7 +2690,7 @@
}
}
}
- FREE_C_HEAP_ARRAY(unsigned long, cpu_map);
+ FREE_C_HEAP_ARRAY(unsigned long, cpu_map, mtInternal);
}
int os::Linux::get_node_by_cpu(int cpu_id) {
@@ -2709,7 +2709,7 @@
os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory;
unsigned long* os::Linux::_numa_all_nodes;
-bool os::uncommit_memory(char* addr, size_t size) {
+bool os::pd_uncommit_memory(char* addr, size_t size) {
uintptr_t res = (uintptr_t) ::mmap(addr, size, PROT_NONE,
MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE|MAP_ANONYMOUS, -1, 0);
return res != (uintptr_t) MAP_FAILED;
@@ -2774,7 +2774,7 @@
// munmap() the guard pages we don't leave a hole in the stack
// mapping. This only affects the main/initial thread, but guard
// against future OS changes
-bool os::create_stack_guard_pages(char* addr, size_t size) {
+bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
uintptr_t stack_extent, stack_base;
bool chk_bounds = NOT_DEBUG(os::Linux::is_initial_thread()) DEBUG_ONLY(true);
if (chk_bounds && get_stack_bounds(&stack_extent, &stack_base)) {
@@ -2847,12 +2847,12 @@
return ::munmap(addr, size) == 0;
}
-char* os::reserve_memory(size_t bytes, char* requested_addr,
+char* os::pd_reserve_memory(size_t bytes, char* requested_addr,
size_t alignment_hint) {
return anon_mmap(requested_addr, bytes, (requested_addr != NULL));
}
-bool os::release_memory(char* addr, size_t size) {
+bool os::pd_release_memory(char* addr, size_t size) {
return anon_munmap(addr, size);
}
@@ -3149,7 +3149,7 @@
// Reserve memory at an arbitrary address, only if that area is
// available (and not reserved for something else).
-char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
const int max_tries = 10;
char* base[max_tries];
size_t size[max_tries];
@@ -4671,7 +4671,7 @@
}
// Map a block of memory.
-char* os::map_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
int prot;
@@ -4701,7 +4701,7 @@
// Remap a block of memory.
-char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
// same as map_memory() on this OS
@@ -4711,7 +4711,7 @@
// Unmap a block of memory.
-bool os::unmap_memory(char* addr, size_t bytes) {
+bool os::pd_unmap_memory(char* addr, size_t bytes) {
return munmap(addr, bytes) == 0;
}
@@ -5447,6 +5447,18 @@
return true;
}
+// Get the default path to the core file
+// Returns the length of the string
+int os::get_core_path(char* buffer, size_t bufferSize) {
+ const char* p = get_current_directory(buffer, bufferSize);
+
+ if (p == NULL) {
+ assert(p != NULL, "failed to get current directory");
+ return 0;
+ }
+
+ return strlen(buffer);
+}
#ifdef JAVASE_EMBEDDED
//
--- a/hotspot/src/os/linux/vm/os_linux.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -287,7 +287,7 @@
};
-class PlatformEvent : public CHeapObj {
+class PlatformEvent : public CHeapObj<mtInternal> {
private:
double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line
volatile int _Event ;
@@ -322,7 +322,7 @@
void SetAssociation (Thread * a) { _Assoc = a ; }
} ;
-class PlatformParker : public CHeapObj {
+class PlatformParker : public CHeapObj<mtInternal> {
protected:
pthread_mutex_t _mutex [1] ;
pthread_cond_t _cond [1] ;
--- a/hotspot/src/os/linux/vm/os_linux.inline.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -99,7 +99,7 @@
// On Linux, reservations are made on a page by page basis, nothing to do.
-inline void os::split_reserved_memory(char *base, size_t size,
+inline void os::pd_split_reserved_memory(char *base, size_t size,
size_t split, bool realloc) {
}
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -126,7 +126,7 @@
}
}
}
- FREE_C_HEAP_ARRAY(char, destfile);
+ FREE_C_HEAP_ARRAY(char, destfile, mtInternal);
}
@@ -153,7 +153,7 @@
const char* tmpdir = os::get_temp_directory();
const char* perfdir = PERFDATA_NAME;
size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
- char* dirname = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
// construct the path name to user specific tmp directory
snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user);
@@ -246,7 +246,7 @@
if (bufsize == -1)
bufsize = 1024;
- char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize);
+ char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
// POSIX interface to getpwuid_r is used on LINUX
struct passwd* p;
@@ -278,14 +278,14 @@
"pw_name zero length");
}
}
- FREE_C_HEAP_ARRAY(char, pwbuf);
+ FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
return NULL;
}
- char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1);
+ char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal);
strcpy(user_name, p->pw_name);
- FREE_C_HEAP_ARRAY(char, pwbuf);
+ FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
return user_name;
}
@@ -328,7 +328,7 @@
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname));
+ char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
@@ -338,7 +338,7 @@
}
char* usrdir_name = NEW_C_HEAP_ARRAY(char,
- strlen(tmpdirname) + strlen(dentry->d_name) + 2);
+ strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);
strcpy(usrdir_name, tmpdirname);
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
@@ -346,7 +346,7 @@
DIR* subdirp = os::opendir(usrdir_name);
if (subdirp == NULL) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
continue;
}
@@ -357,13 +357,13 @@
// symlink can be exploited.
//
if (!is_directory_secure(usrdir_name)) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
os::closedir(subdirp);
continue;
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name));
+ char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
@@ -372,7 +372,7 @@
int result;
char* filename = NEW_C_HEAP_ARRAY(char,
- strlen(usrdir_name) + strlen(udentry->d_name) + 2);
+ strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal);
strcpy(filename, usrdir_name);
strcat(filename, "/");
@@ -381,13 +381,13 @@
// don't follow symbolic links for the file
RESTARTABLE(::lstat(filename, &statbuf), result);
if (result == OS_ERR) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
// skip over files that are not regular files.
if (!S_ISREG(statbuf.st_mode)) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
@@ -397,23 +397,23 @@
if (statbuf.st_ctime > oldest_ctime) {
char* user = strchr(dentry->d_name, '_') + 1;
- if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user);
- oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
+ if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user, mtInternal);
+ oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
strcpy(oldest_user, user);
oldest_ctime = statbuf.st_ctime;
}
}
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf);
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf);
+ FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(oldest_user);
}
@@ -434,7 +434,7 @@
// add 2 for the file separator and a null terminator.
size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
- char* name = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
snprintf(name, nbytes, "%s/%d", dirname, vmid);
return name;
@@ -472,7 +472,7 @@
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "/");
@@ -480,7 +480,7 @@
remove_file(path);
- FREE_C_HEAP_ARRAY(char, path);
+ FREE_C_HEAP_ARRAY(char, path, mtInternal);
}
@@ -517,7 +517,7 @@
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname));
+ char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -556,7 +556,7 @@
errno = 0;
}
os::closedir(dirp);
- FREE_C_HEAP_ARRAY(char, dbuf);
+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// make the user specific temporary directory. Returns true if
@@ -723,11 +723,11 @@
fd = create_sharedmem_resources(dirname, filename, size);
- FREE_C_HEAP_ARRAY(char, user_name);
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
if (fd == -1) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
return NULL;
}
@@ -743,7 +743,7 @@
warning("mmap failed - %s\n", strerror(errno));
}
remove_file(filename);
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
return NULL;
}
@@ -869,7 +869,7 @@
// store file, we don't follow them when attaching either.
//
if (!is_directory_secure(dirname)) {
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
@@ -884,9 +884,9 @@
strcpy(rfilename, filename);
// free the c heap resources that are no longer needed
- if (luser != user) FREE_C_HEAP_ARRAY(char, luser);
- FREE_C_HEAP_ARRAY(char, dirname);
- FREE_C_HEAP_ARRAY(char, filename);
+ if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
// open the shared memory file for the give vmid
fd = open_sharedmem_file(rfilename, file_flags, CHECK);
--- a/hotspot/src/os/posix/vm/os_posix.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/posix/vm/os_posix.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -23,6 +23,7 @@
*/
#include "prims/jvm.h"
+#include "runtime/frame.inline.hpp"
#include "runtime/os.hpp"
#include "utilities/vmError.hpp"
@@ -33,19 +34,19 @@
// Check core dump limit and report possible place where core can be found
void os::check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize) {
+ int n;
struct rlimit rlim;
- static char cwd[O_BUFLEN];
bool success;
- get_current_directory(cwd, sizeof(cwd));
+ n = get_core_path(buffer, bufferSize);
if (getrlimit(RLIMIT_CORE, &rlim) != 0) {
- jio_snprintf(buffer, bufferSize, "%s/core or core.%d (may not exist)", cwd, current_process_id());
+ jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (may not exist)", current_process_id());
success = true;
} else {
switch(rlim.rlim_cur) {
case RLIM_INFINITY:
- jio_snprintf(buffer, bufferSize, "%s/core or core.%d", cwd, current_process_id());
+ jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d", current_process_id());
success = true;
break;
case 0:
@@ -53,7 +54,7 @@
success = false;
break;
default:
- jio_snprintf(buffer, bufferSize, "%s/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", cwd, current_process_id(), (unsigned long)(rlim.rlim_cur >> 10));
+ jio_snprintf(buffer + n, bufferSize - n, "/core or core.%d (max size %lu kB). To ensure a full core dump, try \"ulimit -c unlimited\" before starting Java again", current_process_id(), (unsigned long)(rlim.rlim_cur >> 10));
success = true;
break;
}
@@ -61,6 +62,23 @@
VMError::report_coredump_status(buffer, success);
}
+address os::get_caller_pc(int n) {
+#ifdef _NMT_NOINLINE_
+ n ++;
+#endif
+ frame fr = os::current_frame();
+ while (n > 0 && fr.pc() &&
+ !os::is_first_C_frame(&fr) && fr.sender_pc()) {
+ fr = os::get_sender_for_C_frame(&fr);
+ n --;
+ }
+ if (n == 0) {
+ return fr.pc();
+ } else {
+ return NULL;
+ }
+}
+
int os::get_last_error() {
return errno;
}
--- a/hotspot/src/os/solaris/dtrace/hs_private.d Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/solaris/dtrace/hs_private.d Wed Jul 05 18:16:35 2017 +0200
@@ -23,7 +23,6 @@
*/
provider hs_private {
- probe hashtable__new_entry(void*, uintptr_t, void*);
probe safepoint__begin();
probe safepoint__end();
probe cms__initmark__begin();
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -546,7 +546,7 @@
// Find the number of processors in the processor set.
if (pset_info(pset, NULL, id_length, NULL) == 0) {
// Make up an array to hold their ids.
- *id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length);
+ *id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length, mtInternal);
// Fill in the array with their processor ids.
if (pset_info(pset, NULL, id_length, *id_array) == 0) {
result = true;
@@ -577,7 +577,7 @@
// Find the number of processors online.
*id_length = sysconf(_SC_NPROCESSORS_ONLN);
// Make up an array to hold their ids.
- *id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length);
+ *id_array = NEW_C_HEAP_ARRAY(processorid_t, *id_length, mtInternal);
// Processors need not be numbered consecutively.
long found = 0;
processorid_t next = 0;
@@ -629,7 +629,7 @@
// The next id, to limit loops.
const processorid_t limit_id = max_id + 1;
// Make up markers for available processors.
- bool* available_id = NEW_C_HEAP_ARRAY(bool, limit_id);
+ bool* available_id = NEW_C_HEAP_ARRAY(bool, limit_id, mtInternal);
for (uint c = 0; c < limit_id; c += 1) {
available_id[c] = false;
}
@@ -666,7 +666,7 @@
}
}
if (available_id != NULL) {
- FREE_C_HEAP_ARRAY(bool, available_id);
+ FREE_C_HEAP_ARRAY(bool, available_id, mtInternal);
}
return true;
}
@@ -698,7 +698,7 @@
}
}
if (id_array != NULL) {
- FREE_C_HEAP_ARRAY(processorid_t, id_array);
+ FREE_C_HEAP_ARRAY(processorid_t, id_array, mtInternal);
}
return result;
}
@@ -771,8 +771,8 @@
// code needs to be changed accordingly.
// The next few definitions allow the code to be verbatim:
-#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n))
-#define free(p) FREE_C_HEAP_ARRAY(char, p)
+#define malloc(n) (char*)NEW_C_HEAP_ARRAY(char, (n), mtInternal)
+#define free(p) FREE_C_HEAP_ARRAY(char, p, mtInternal)
#define getenv(n) ::getenv(n)
#define EXTENSIONS_DIR "/lib/ext"
@@ -1927,11 +1927,11 @@
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
- FREE_C_HEAP_ARRAY(char, pelements[i]);
+ FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal);
}
}
if (pelements != NULL) {
- FREE_C_HEAP_ARRAY(char*, pelements);
+ FREE_C_HEAP_ARRAY(char*, pelements, mtInternal);
}
} else {
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
@@ -2662,17 +2662,17 @@
// pending_signals has one int per signal
// The additional signal is for SIGEXIT - exit signal to signal_thread
- pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1));
+ pending_signals = (jint *)os::malloc(sizeof(jint) * (Sigexit+1), mtInternal);
memset(pending_signals, 0, (sizeof(jint) * (Sigexit+1)));
if (UseSignalChaining) {
chainedsigactions = (struct sigaction *)malloc(sizeof(struct sigaction)
- * (Maxsignum + 1));
+ * (Maxsignum + 1), mtInternal);
memset(chainedsigactions, 0, (sizeof(struct sigaction) * (Maxsignum + 1)));
- preinstalled_sigs = (int *)os::malloc(sizeof(int) * (Maxsignum + 1));
+ preinstalled_sigs = (int *)os::malloc(sizeof(int) * (Maxsignum + 1), mtInternal);
memset(preinstalled_sigs, 0, (sizeof(int) * (Maxsignum + 1)));
}
- ourSigFlags = (int*)malloc(sizeof(int) * (Maxsignum + 1 ));
+ ourSigFlags = (int*)malloc(sizeof(int) * (Maxsignum + 1 ), mtInternal);
memset(ourSigFlags, 0, sizeof(int) * (Maxsignum + 1));
}
@@ -2760,7 +2760,7 @@
return page_size;
}
-bool os::commit_memory(char* addr, size_t bytes, bool exec) {
+bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
int prot = exec ? PROT_READ|PROT_WRITE|PROT_EXEC : PROT_READ|PROT_WRITE;
size_t size = bytes;
char *res = Solaris::mmap_chunk(addr, size, MAP_PRIVATE|MAP_FIXED, prot);
@@ -2773,7 +2773,7 @@
return false;
}
-bool os::commit_memory(char* addr, size_t bytes, size_t alignment_hint,
+bool os::pd_commit_memory(char* addr, size_t bytes, size_t alignment_hint,
bool exec) {
if (commit_memory(addr, bytes, exec)) {
if (UseMPSS && alignment_hint > (size_t)vm_page_size()) {
@@ -2803,14 +2803,14 @@
}
// Uncommit the pages in a specified region.
-void os::free_memory(char* addr, size_t bytes, size_t alignment_hint) {
+void os::pd_free_memory(char* addr, size_t bytes, size_t alignment_hint) {
if (madvise(addr, bytes, MADV_FREE) < 0) {
debug_only(warning("MADV_FREE failed."));
return;
}
}
-bool os::create_stack_guard_pages(char* addr, size_t size) {
+bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
return os::commit_memory(addr, size);
}
@@ -2819,7 +2819,7 @@
}
// Change the page size in a given range.
-void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
+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) {
@@ -3006,7 +3006,7 @@
return end;
}
-bool os::uncommit_memory(char* addr, size_t bytes) {
+bool os::pd_uncommit_memory(char* addr, size_t bytes) {
size_t size = bytes;
// Map uncommitted pages PROT_NONE so we fail early if we touch an
// uncommitted page. Otherwise, the read/write might succeed if we
@@ -3045,7 +3045,7 @@
return mmap_chunk(addr, bytes, flags, PROT_NONE);
}
-char* os::reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
+char* os::pd_reserve_memory(size_t bytes, char* requested_addr, size_t alignment_hint) {
char* addr = Solaris::anon_mmap(requested_addr, bytes, alignment_hint, (requested_addr != NULL));
guarantee(requested_addr == NULL || requested_addr == addr,
@@ -3056,7 +3056,7 @@
// Reserve memory at an arbitrary address, only if that area is
// available (and not reserved for something else).
-char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
const int max_tries = 10;
char* base[max_tries];
size_t size[max_tries];
@@ -3178,7 +3178,7 @@
return (i < max_tries) ? requested_addr : NULL;
}
-bool os::release_memory(char* addr, size_t bytes) {
+bool os::pd_release_memory(char* addr, size_t bytes) {
size_t size = bytes;
return munmap(addr, size) == 0;
}
@@ -4792,7 +4792,7 @@
lwpSize = 16*1024;
for (;;) {
::lseek64 (lwpFile, 0, SEEK_SET);
- lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize);
+ lwpArray = (prheader_t *)NEW_C_HEAP_ARRAY(char, lwpSize, mtInternal);
if (::read(lwpFile, lwpArray, lwpSize) < 0) {
if (ThreadPriorityVerbose) warning("Error reading /proc/self/lstatus\n");
break;
@@ -4810,10 +4810,10 @@
break;
}
lwpSize = lwpArray->pr_nent * lwpArray->pr_entsize;
- FREE_C_HEAP_ARRAY(char, lwpArray); // retry.
- }
-
- FREE_C_HEAP_ARRAY(char, lwpArray);
+ FREE_C_HEAP_ARRAY(char, lwpArray, mtInternal); // retry.
+ }
+
+ FREE_C_HEAP_ARRAY(char, lwpArray, mtInternal);
::close (lwpFile);
if (ThreadPriorityVerbose) {
if (isT2) tty->print_cr("We are running with a T2 libthread\n");
@@ -5137,9 +5137,9 @@
UseNUMA = false;
} else {
size_t lgrp_limit = os::numa_get_groups_num();
- int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
+ int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit, mtInternal);
size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
- FREE_C_HEAP_ARRAY(int, lgrp_ids);
+ FREE_C_HEAP_ARRAY(int, lgrp_ids, mtInternal);
if (lgrp_num < 2) {
// There's only one locality group, disable NUMA.
UseNUMA = false;
@@ -5485,7 +5485,7 @@
}
// Map a block of memory.
-char* os::map_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
int prot;
@@ -5517,7 +5517,7 @@
// Remap a block of memory.
-char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
// same as map_memory() on this OS
@@ -5527,7 +5527,7 @@
// Unmap a block of memory.
-bool os::unmap_memory(char* addr, size_t bytes) {
+bool os::pd_unmap_memory(char* addr, size_t bytes) {
return munmap(addr, bytes) == 0;
}
@@ -6537,3 +6537,16 @@
INTERRUPTIBLE_RETURN_INT_NORESTART(::bind(fd, him, len),\
os::Solaris::clear_interrupted);
}
+
+// Get the default path to the core file
+// Returns the length of the string
+int os::get_core_path(char* buffer, size_t bufferSize) {
+ const char* p = get_current_directory(buffer, bufferSize);
+
+ if (p == NULL) {
+ assert(p != NULL, "failed to get current directory");
+ return 0;
+ }
+
+ return strlen(buffer);
+}
--- a/hotspot/src/os/solaris/vm/os_solaris.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -346,7 +346,7 @@
};
-class PlatformEvent : public CHeapObj {
+class PlatformEvent : public CHeapObj<mtInternal> {
private:
double CachePad [4] ; // increase odds that _mutex is sole occupant of cache line
volatile int _Event ;
@@ -383,7 +383,7 @@
void unpark () ;
} ;
-class PlatformParker : public CHeapObj {
+class PlatformParker : public CHeapObj<mtInternal> {
protected:
mutex_t _mutex [1] ;
cond_t _cond [1] ;
--- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -71,7 +71,7 @@
// On Solaris, reservations are made on a page by page basis, nothing to do.
-inline void os::split_reserved_memory(char *base, size_t size,
+inline void os::pd_split_reserved_memory(char *base, size_t size,
size_t split, bool realloc) {
}
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -128,7 +128,7 @@
}
}
}
- FREE_C_HEAP_ARRAY(char, destfile);
+ FREE_C_HEAP_ARRAY(char, destfile, mtInternal);
}
@@ -155,7 +155,7 @@
const char* tmpdir = os::get_temp_directory();
const char* perfdir = PERFDATA_NAME;
size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
- char* dirname = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
// construct the path name to user specific tmp directory
snprintf(dirname, nbytes, "%s/%s_%s", tmpdir, perfdir, user);
@@ -248,7 +248,7 @@
if (bufsize == -1)
bufsize = 1024;
- char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize);
+ char* pwbuf = NEW_C_HEAP_ARRAY(char, bufsize, mtInternal);
#ifdef _GNU_SOURCE
struct passwd* p = NULL;
@@ -269,14 +269,14 @@
"pw_name zero length");
}
}
- FREE_C_HEAP_ARRAY(char, pwbuf);
+ FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
return NULL;
}
- char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1);
+ char* user_name = NEW_C_HEAP_ARRAY(char, strlen(p->pw_name) + 1, mtInternal);
strcpy(user_name, p->pw_name);
- FREE_C_HEAP_ARRAY(char, pwbuf);
+ FREE_C_HEAP_ARRAY(char, pwbuf, mtInternal);
return user_name;
}
@@ -319,7 +319,7 @@
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname));
+ char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
@@ -329,7 +329,7 @@
}
char* usrdir_name = NEW_C_HEAP_ARRAY(char,
- strlen(tmpdirname) + strlen(dentry->d_name) + 2);
+ strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);
strcpy(usrdir_name, tmpdirname);
strcat(usrdir_name, "/");
strcat(usrdir_name, dentry->d_name);
@@ -337,7 +337,7 @@
DIR* subdirp = os::opendir(usrdir_name);
if (subdirp == NULL) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
continue;
}
@@ -348,13 +348,13 @@
// symlink can be exploited.
//
if (!is_directory_secure(usrdir_name)) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
os::closedir(subdirp);
continue;
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name));
+ char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
@@ -363,7 +363,7 @@
int result;
char* filename = NEW_C_HEAP_ARRAY(char,
- strlen(usrdir_name) + strlen(udentry->d_name) + 2);
+ strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal);
strcpy(filename, usrdir_name);
strcat(filename, "/");
@@ -372,13 +372,13 @@
// don't follow symbolic links for the file
RESTARTABLE(::lstat(filename, &statbuf), result);
if (result == OS_ERR) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
// skip over files that are not regular files.
if (!S_ISREG(statbuf.st_mode)) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
@@ -388,23 +388,23 @@
if (statbuf.st_ctime > oldest_ctime) {
char* user = strchr(dentry->d_name, '_') + 1;
- if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user);
- oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
+ if (oldest_user != NULL) FREE_C_HEAP_ARRAY(char, oldest_user, mtInternal);
+ oldest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
strcpy(oldest_user, user);
oldest_ctime = statbuf.st_ctime;
}
}
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf);
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf);
+ FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(oldest_user);
}
@@ -471,7 +471,7 @@
// add 2 for the file separator and a NULL terminator.
size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
- char* name = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
snprintf(name, nbytes, "%s/%d", dirname, vmid);
return name;
@@ -509,7 +509,7 @@
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "/");
@@ -517,7 +517,7 @@
remove_file(path);
- FREE_C_HEAP_ARRAY(char, path);
+ FREE_C_HEAP_ARRAY(char, path, mtInternal);
}
@@ -554,7 +554,7 @@
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname));
+ char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -593,7 +593,7 @@
errno = 0;
}
os::closedir(dirp);
- FREE_C_HEAP_ARRAY(char, dbuf);
+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// make the user specific temporary directory. Returns true if
@@ -738,11 +738,11 @@
fd = create_sharedmem_resources(dirname, filename, size);
- FREE_C_HEAP_ARRAY(char, user_name);
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, user_name, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
if (fd == -1) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
return NULL;
}
@@ -758,7 +758,7 @@
warning("mmap failed - %s\n", strerror(errno));
}
remove_file(filename);
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
return NULL;
}
@@ -884,7 +884,7 @@
// store file, we don't follow them when attaching either.
//
if (!is_directory_secure(dirname)) {
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
@@ -899,9 +899,9 @@
strcpy(rfilename, filename);
// free the c heap resources that are no longer needed
- if (luser != user) FREE_C_HEAP_ARRAY(char, luser);
- FREE_C_HEAP_ARRAY(char, dirname);
- FREE_C_HEAP_ARRAY(char, filename);
+ if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
// open the shared memory file for the give vmid
fd = open_sharedmem_file(rfilename, file_flags, CHECK);
--- a/hotspot/src/os/windows/vm/os_windows.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -96,7 +96,6 @@
#include <io.h>
#include <process.h> // For _beginthreadex(), _endthreadex()
#include <imagehlp.h> // For os::dll_address_to_function_name
-
/* for enumerating dll libraries */
#include <vdmdbg.h>
@@ -214,13 +213,13 @@
}
}
- home_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + 1);
+ home_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + 1, mtInternal);
if (home_path == NULL)
return;
strcpy(home_path, home_dir);
Arguments::set_java_home(home_path);
- dll_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + strlen(bin) + 1);
+ dll_path = NEW_C_HEAP_ARRAY(char, strlen(home_dir) + strlen(bin) + 1, mtInternal);
if (dll_path == NULL)
return;
strcpy(dll_path, home_dir);
@@ -251,7 +250,7 @@
char *path_str = ::getenv("PATH");
library_path = NEW_C_HEAP_ARRAY(char, MAX_PATH * 5 + sizeof(PACKAGE_DIR) +
- sizeof(BIN_DIR) + (path_str ? strlen(path_str) : 0) + 10);
+ sizeof(BIN_DIR) + (path_str ? strlen(path_str) : 0) + 10, mtInternal);
library_path[0] = '\0';
@@ -280,7 +279,7 @@
strcat(library_path, ";.");
Arguments::set_library_path(library_path);
- FREE_C_HEAP_ARRAY(char, library_path);
+ FREE_C_HEAP_ARRAY(char, library_path, mtInternal);
}
/* Default extensions directory */
@@ -300,7 +299,7 @@
{
#define ENDORSED_DIR "\\lib\\endorsed"
size_t len = strlen(Arguments::get_java_home()) + sizeof(ENDORSED_DIR);
- char * buf = NEW_C_HEAP_ARRAY(char, len);
+ char * buf = NEW_C_HEAP_ARRAY(char, len, mtInternal);
sprintf(buf, "%s%s", Arguments::get_java_home(), ENDORSED_DIR);
Arguments::set_endorsed_dirs(buf);
#undef ENDORSED_DIR
@@ -324,6 +323,23 @@
os::breakpoint();
}
+/*
+ * RtlCaptureStackBackTrace Windows API may not exist prior to Windows XP.
+ * So far, this method is only used by Native Memory Tracking, which is
+ * only supported on Windows XP or later.
+ */
+address os::get_caller_pc(int n) {
+#ifdef _NMT_NOINLINE_
+ n ++;
+#endif
+ address pc;
+ if (os::Kernel32Dll::RtlCaptureStackBackTrace(n + 1, 1, (PVOID*)&pc, NULL) == 1) {
+ return pc;
+ }
+ return NULL;
+}
+
+
// os::current_stack_base()
//
// Returns the base of the stack, which is the stack's
@@ -1014,7 +1030,7 @@
os::opendir(const char *dirname)
{
assert(dirname != NULL, "just checking"); // hotspot change
- DIR *dirp = (DIR *)malloc(sizeof(DIR));
+ DIR *dirp = (DIR *)malloc(sizeof(DIR), mtInternal);
DWORD fattr; // hotspot change
char alt_dirname[4] = { 0, 0, 0, 0 };
@@ -1036,9 +1052,9 @@
dirname = alt_dirname;
}
- dirp->path = (char *)malloc(strlen(dirname) + 5);
+ dirp->path = (char *)malloc(strlen(dirname) + 5, mtInternal);
if (dirp->path == 0) {
- free(dirp);
+ free(dirp, mtInternal);
errno = ENOMEM;
return 0;
}
@@ -1046,13 +1062,13 @@
fattr = GetFileAttributes(dirp->path);
if (fattr == 0xffffffff) {
- free(dirp->path);
- free(dirp);
+ free(dirp->path, mtInternal);
+ free(dirp, mtInternal);
errno = ENOENT;
return 0;
} else if ((fattr & FILE_ATTRIBUTE_DIRECTORY) == 0) {
- free(dirp->path);
- free(dirp);
+ free(dirp->path, mtInternal);
+ free(dirp, mtInternal);
errno = ENOTDIR;
return 0;
}
@@ -1070,8 +1086,8 @@
dirp->handle = FindFirstFile(dirp->path, &dirp->find_data);
if (dirp->handle == INVALID_HANDLE_VALUE) {
if (GetLastError() != ERROR_FILE_NOT_FOUND) {
- free(dirp->path);
- free(dirp);
+ free(dirp->path, mtInternal);
+ free(dirp, mtInternal);
errno = EACCES;
return 0;
}
@@ -1114,8 +1130,8 @@
}
dirp->handle = INVALID_HANDLE_VALUE;
}
- free(dirp->path);
- free(dirp);
+ free(dirp->path, mtInternal);
+ free(dirp, mtInternal);
return 0;
}
@@ -1176,11 +1192,11 @@
// release the storage
for (int i = 0 ; i < n ; i++) {
if (pelements[i] != NULL) {
- FREE_C_HEAP_ARRAY(char, pelements[i]);
+ FREE_C_HEAP_ARRAY(char, pelements[i], mtInternal);
}
}
if (pelements != NULL) {
- FREE_C_HEAP_ARRAY(char*, pelements);
+ FREE_C_HEAP_ARRAY(char*, pelements, mtInternal);
}
} else {
jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname);
@@ -2637,7 +2653,7 @@
void free_node_list() {
if (_numa_used_node_list != NULL) {
- FREE_C_HEAP_ARRAY(int, _numa_used_node_list);
+ FREE_C_HEAP_ARRAY(int, _numa_used_node_list, mtInternal);
}
}
@@ -2659,7 +2675,7 @@
ULONG highest_node_number;
if (!os::Kernel32Dll::GetNumaHighestNodeNumber(&highest_node_number)) return false;
free_node_list();
- _numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number + 1);
+ _numa_used_node_list = NEW_C_HEAP_ARRAY(int, highest_node_number + 1, mtInternal);
for (unsigned int i = 0; i <= highest_node_number; i++) {
ULONGLONG proc_mask_numa_node;
if (!os::Kernel32Dll::GetNumaNodeProcessorMask(i, &proc_mask_numa_node)) return false;
@@ -2918,7 +2934,7 @@
// On win32, one cannot release just a part of reserved memory, it's an
// all or nothing deal. When we split a reservation, we must break the
// reservation into two reservations.
-void os::split_reserved_memory(char *base, size_t size, size_t split,
+void os::pd_split_reserved_memory(char *base, size_t size, size_t split,
bool realloc) {
if (size > 0) {
release_memory(base, size);
@@ -2931,7 +2947,7 @@
}
}
-char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
+char* os::pd_reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
assert((size_t)addr % os::vm_allocation_granularity() == 0,
"reserve alignment");
assert(bytes % os::vm_allocation_granularity() == 0, "reserve block size");
@@ -2964,7 +2980,7 @@
// Reserve memory at an arbitrary address, only if that area is
// available (and not reserved for something else).
-char* os::attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
+char* os::pd_attempt_reserve_memory_at(size_t bytes, char* requested_addr) {
// Windows os::reserve_memory() fails of the requested address range is
// not avilable.
return reserve_memory(bytes, requested_addr);
@@ -3027,7 +3043,7 @@
void os::print_statistics() {
}
-bool os::commit_memory(char* addr, size_t bytes, bool exec) {
+bool os::pd_commit_memory(char* addr, size_t bytes, bool exec) {
if (bytes == 0) {
// Don't bother the OS with noops.
return true;
@@ -3075,26 +3091,26 @@
return true;
}
-bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
+bool os::pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
bool exec) {
return commit_memory(addr, size, exec);
}
-bool os::uncommit_memory(char* addr, size_t bytes) {
+bool os::pd_uncommit_memory(char* addr, size_t bytes) {
if (bytes == 0) {
// Don't bother the OS with noops.
return true;
}
assert((size_t) addr % os::vm_page_size() == 0, "uncommit on page boundaries");
assert(bytes % os::vm_page_size() == 0, "uncommit in page-sized chunks");
- return VirtualFree(addr, bytes, MEM_DECOMMIT) != 0;
-}
-
-bool os::release_memory(char* addr, size_t bytes) {
+ return (VirtualFree(addr, bytes, MEM_DECOMMIT) != 0);
+}
+
+bool os::pd_release_memory(char* addr, size_t bytes) {
return VirtualFree(addr, 0, MEM_RELEASE) != 0;
}
-bool os::create_stack_guard_pages(char* addr, size_t size) {
+bool os::pd_create_stack_guard_pages(char* addr, size_t size) {
return os::commit_memory(addr, size);
}
@@ -3141,8 +3157,8 @@
return VirtualProtect(addr, bytes, PAGE_READWRITE, &old_status) != 0;
}
-void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
-void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) { }
+void os::pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint) { }
+void os::pd_free_memory(char *addr, size_t bytes, size_t alignment_hint) { }
void os::numa_make_global(char *addr, size_t bytes) { }
void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { }
bool os::numa_topology_changed() { return false; }
@@ -4276,14 +4292,14 @@
numEvents = MAX_INPUT_EVENTS;
}
- lpBuffer = (INPUT_RECORD *)os::malloc(numEvents * sizeof(INPUT_RECORD));
+ lpBuffer = (INPUT_RECORD *)os::malloc(numEvents * sizeof(INPUT_RECORD), mtInternal);
if (lpBuffer == NULL) {
return FALSE;
}
error = ::PeekConsoleInput(han, lpBuffer, numEvents, &numEventsRead);
if (error == 0) {
- os::free(lpBuffer);
+ os::free(lpBuffer, mtInternal);
return FALSE;
}
@@ -4304,7 +4320,7 @@
}
if(lpBuffer != NULL) {
- os::free(lpBuffer);
+ os::free(lpBuffer, mtInternal);
}
*pbytes = (long) actualLength;
@@ -4312,7 +4328,7 @@
}
// Map a block of memory.
-char* os::map_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_map_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
HANDLE hFile;
@@ -4432,7 +4448,7 @@
// Remap a block of memory.
-char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
+char* os::pd_remap_memory(int fd, const char* file_name, size_t file_offset,
char *addr, size_t bytes, bool read_only,
bool allow_exec) {
// This OS does not allow existing memory maps to be remapped so we
@@ -4445,15 +4461,15 @@
// call above and the map_memory() call below where a thread in native
// code may be able to access an address that is no longer mapped.
- return os::map_memory(fd, file_name, file_offset, addr, bytes, read_only,
- allow_exec);
+ return os::map_memory(fd, file_name, file_offset, addr, bytes,
+ read_only, allow_exec);
}
// Unmap a block of memory.
// Returns true=success, otherwise false.
-bool os::unmap_memory(char* addr, size_t bytes) {
+bool os::pd_unmap_memory(char* addr, size_t bytes) {
BOOL result = UnmapViewOfFile(addr);
if (result == 0) {
if (PrintMiscellaneous && Verbose) {
@@ -4931,11 +4947,15 @@
typedef LPVOID (WINAPI *VirtualAllocExNuma_Fn) (HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD);
typedef BOOL (WINAPI *GetNumaHighestNodeNumber_Fn) (PULONG);
typedef BOOL (WINAPI *GetNumaNodeProcessorMask_Fn) (UCHAR, PULONGLONG);
+typedef USHORT (WINAPI* RtlCaptureStackBackTrace_Fn)(ULONG, ULONG, PVOID*, PULONG);
GetLargePageMinimum_Fn os::Kernel32Dll::_GetLargePageMinimum = NULL;
VirtualAllocExNuma_Fn os::Kernel32Dll::_VirtualAllocExNuma = NULL;
GetNumaHighestNodeNumber_Fn os::Kernel32Dll::_GetNumaHighestNodeNumber = NULL;
GetNumaNodeProcessorMask_Fn os::Kernel32Dll::_GetNumaNodeProcessorMask = NULL;
+RtlCaptureStackBackTrace_Fn os::Kernel32Dll::_RtlCaptureStackBackTrace = NULL;
+
+
BOOL os::Kernel32Dll::initialized = FALSE;
SIZE_T os::Kernel32Dll::GetLargePageMinimum() {
assert(initialized && _GetLargePageMinimum != NULL,
@@ -4978,6 +4998,19 @@
return _GetNumaNodeProcessorMask(node, proc_mask);
}
+USHORT os::Kernel32Dll::RtlCaptureStackBackTrace(ULONG FrameToSkip,
+ ULONG FrameToCapture, PVOID* BackTrace, PULONG BackTraceHash) {
+ if (!initialized) {
+ initialize();
+ }
+
+ if (_RtlCaptureStackBackTrace != NULL) {
+ return _RtlCaptureStackBackTrace(FrameToSkip, FrameToCapture,
+ BackTrace, BackTraceHash);
+ } else {
+ return 0;
+ }
+}
void os::Kernel32Dll::initializeCommon() {
if (!initialized) {
@@ -4987,6 +5020,7 @@
_VirtualAllocExNuma = (VirtualAllocExNuma_Fn)::GetProcAddress(handle, "VirtualAllocExNuma");
_GetNumaHighestNodeNumber = (GetNumaHighestNodeNumber_Fn)::GetProcAddress(handle, "GetNumaHighestNodeNumber");
_GetNumaNodeProcessorMask = (GetNumaNodeProcessorMask_Fn)::GetProcAddress(handle, "GetNumaNodeProcessorMask");
+ _RtlCaptureStackBackTrace = (RtlCaptureStackBackTrace_Fn)::GetProcAddress(handle, "RtlCaptureStackBackTrace");
initialized = TRUE;
}
}
@@ -5101,7 +5135,6 @@
Module32Next_Fn os::Kernel32Dll::_Module32Next = NULL;
GetNativeSystemInfo_Fn os::Kernel32Dll::_GetNativeSystemInfo = NULL;
-
void os::Kernel32Dll::initialize() {
if (!initialized) {
HMODULE handle = ::GetModuleHandle("Kernel32.dll");
@@ -5179,8 +5212,6 @@
_GetNativeSystemInfo(lpSystemInfo);
}
-
-
// PSAPI API
--- a/hotspot/src/os/windows/vm/os_windows.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/windows/vm/os_windows.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -98,7 +98,7 @@
static LONG WINAPI serialize_fault_filter(struct _EXCEPTION_POINTERS* e);
};
-class PlatformEvent : public CHeapObj {
+class PlatformEvent : public CHeapObj<mtInternal> {
private:
double CachePad [4] ; // increase odds that _Event is sole occupant of cache line
volatile int _Event ;
@@ -124,7 +124,7 @@
-class PlatformParker : public CHeapObj {
+class PlatformParker : public CHeapObj<mtInternal> {
protected:
HANDLE _ParkEvent ;
@@ -182,6 +182,9 @@
static BOOL GetNumaHighestNodeNumber(PULONG);
static BOOL GetNumaNodeProcessorMask(UCHAR, PULONGLONG);
+ // Stack walking
+ static USHORT RtlCaptureStackBackTrace(ULONG, ULONG, PVOID*, PULONG);
+
private:
// GetLargePageMinimum available on Windows Vista/Windows Server 2003
// and later
@@ -191,6 +194,7 @@
static LPVOID (WINAPI *_VirtualAllocExNuma) (HANDLE, LPVOID, SIZE_T, DWORD, DWORD, DWORD);
static BOOL (WINAPI *_GetNumaHighestNodeNumber) (PULONG);
static BOOL (WINAPI *_GetNumaNodeProcessorMask) (UCHAR, PULONGLONG);
+ static USHORT (WINAPI *_RtlCaptureStackBackTrace)(ULONG, ULONG, PVOID*, PULONG);
static BOOL initialized;
static void initialize();
--- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -120,7 +120,7 @@
}
}
- FREE_C_HEAP_ARRAY(char, destfile);
+ FREE_C_HEAP_ARRAY(char, destfile, mtInternal);
}
// Shared Memory Implementation Details
@@ -157,7 +157,7 @@
const char* tmpdir = os::get_temp_directory();
const char* perfdir = PERFDATA_NAME;
size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3;
- char* dirname = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* dirname = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
// construct the path name to user specific tmp directory
_snprintf(dirname, nbytes, "%s\\%s_%s", tmpdir, perfdir, user);
@@ -281,7 +281,7 @@
}
}
- char* user_name = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
+ char* user_name = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
strcpy(user_name, user);
return user_name;
@@ -315,7 +315,7 @@
// to determine the user name for the process id.
//
struct dirent* dentry;
- char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname));
+ char* tdbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(tmpdirname), mtInternal);
errno = 0;
while ((dentry = os::readdir(tmpdirp, (struct dirent *)tdbuf)) != NULL) {
@@ -325,7 +325,7 @@
}
char* usrdir_name = NEW_C_HEAP_ARRAY(char,
- strlen(tmpdirname) + strlen(dentry->d_name) + 2);
+ strlen(tmpdirname) + strlen(dentry->d_name) + 2, mtInternal);
strcpy(usrdir_name, tmpdirname);
strcat(usrdir_name, "\\");
strcat(usrdir_name, dentry->d_name);
@@ -333,7 +333,7 @@
DIR* subdirp = os::opendir(usrdir_name);
if (subdirp == NULL) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
continue;
}
@@ -344,13 +344,13 @@
// symlink can be exploited.
//
if (!is_directory_secure(usrdir_name)) {
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
os::closedir(subdirp);
continue;
}
struct dirent* udentry;
- char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name));
+ char* udbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(usrdir_name), mtInternal);
errno = 0;
while ((udentry = os::readdir(subdirp, (struct dirent *)udbuf)) != NULL) {
@@ -358,20 +358,20 @@
struct stat statbuf;
char* filename = NEW_C_HEAP_ARRAY(char,
- strlen(usrdir_name) + strlen(udentry->d_name) + 2);
+ strlen(usrdir_name) + strlen(udentry->d_name) + 2, mtInternal);
strcpy(filename, usrdir_name);
strcat(filename, "\\");
strcat(filename, udentry->d_name);
if (::stat(filename, &statbuf) == OS_ERR) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
// skip over files that are not regular files.
if ((statbuf.st_mode & S_IFMT) != S_IFREG) {
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
continue;
}
@@ -393,22 +393,22 @@
if (statbuf.st_ctime > latest_ctime) {
char* user = strchr(dentry->d_name, '_') + 1;
- if (latest_user != NULL) FREE_C_HEAP_ARRAY(char, latest_user);
- latest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1);
+ if (latest_user != NULL) FREE_C_HEAP_ARRAY(char, latest_user, mtInternal);
+ latest_user = NEW_C_HEAP_ARRAY(char, strlen(user)+1, mtInternal);
strcpy(latest_user, user);
latest_ctime = statbuf.st_ctime;
}
- FREE_C_HEAP_ARRAY(char, filename);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
}
}
os::closedir(subdirp);
- FREE_C_HEAP_ARRAY(char, udbuf);
- FREE_C_HEAP_ARRAY(char, usrdir_name);
+ FREE_C_HEAP_ARRAY(char, udbuf, mtInternal);
+ FREE_C_HEAP_ARRAY(char, usrdir_name, mtInternal);
}
os::closedir(tmpdirp);
- FREE_C_HEAP_ARRAY(char, tdbuf);
+ FREE_C_HEAP_ARRAY(char, tdbuf, mtInternal);
return(latest_user);
}
@@ -453,7 +453,7 @@
// about a name containing a '-' characters.
//
nbytes += UINT_CHARS;
- char* name = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
_snprintf(name, nbytes, "%s_%s_%u", PERFDATA_NAME, user, vmid);
return name;
@@ -469,7 +469,7 @@
// add 2 for the file separator and a null terminator.
size_t nbytes = strlen(dirname) + UINT_CHARS + 2;
- char* name = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* name = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
_snprintf(name, nbytes, "%s\\%d", dirname, vmid);
return name;
@@ -485,7 +485,7 @@
static void remove_file(const char* dirname, const char* filename) {
size_t nbytes = strlen(dirname) + strlen(filename) + 2;
- char* path = NEW_C_HEAP_ARRAY(char, nbytes);
+ char* path = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
strcpy(path, dirname);
strcat(path, "\\");
@@ -500,7 +500,7 @@
}
}
- FREE_C_HEAP_ARRAY(char, path);
+ FREE_C_HEAP_ARRAY(char, path, mtInternal);
}
// returns true if the process represented by pid is alive, otherwise
@@ -638,7 +638,7 @@
// opendir/readdir.
//
struct dirent* entry;
- char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname));
+ char* dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(dirname), mtInternal);
errno = 0;
while ((entry = os::readdir(dirp, (struct dirent *)dbuf)) != NULL) {
@@ -681,7 +681,7 @@
errno = 0;
}
os::closedir(dirp);
- FREE_C_HEAP_ARRAY(char, dbuf);
+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
}
// create a file mapping object with the requested name, and size
@@ -747,11 +747,11 @@
// be an ACL we enlisted. free the resources.
//
if (success && exists && pACL != NULL && !isdefault) {
- FREE_C_HEAP_ARRAY(char, pACL);
+ FREE_C_HEAP_ARRAY(char, pACL, mtInternal);
}
// free the security descriptor
- FREE_C_HEAP_ARRAY(char, pSD);
+ FREE_C_HEAP_ARRAY(char, pSD, mtInternal);
}
}
@@ -766,7 +766,7 @@
lpSA->lpSecurityDescriptor = NULL;
// free the security attributes structure
- FREE_C_HEAP_ARRAY(char, lpSA);
+ FREE_C_HEAP_ARRAY(char, lpSA, mtInternal);
}
}
@@ -805,7 +805,7 @@
}
}
- token_buf = (PTOKEN_USER) NEW_C_HEAP_ARRAY(char, rsize);
+ token_buf = (PTOKEN_USER) NEW_C_HEAP_ARRAY(char, rsize, mtInternal);
// get the user token information
if (!GetTokenInformation(hAccessToken, TokenUser, token_buf, rsize, &rsize)) {
@@ -813,28 +813,28 @@
warning("GetTokenInformation failure: lasterror = %d,"
" rsize = %d\n", GetLastError(), rsize);
}
- FREE_C_HEAP_ARRAY(char, token_buf);
+ FREE_C_HEAP_ARRAY(char, token_buf, mtInternal);
CloseHandle(hAccessToken);
return NULL;
}
DWORD nbytes = GetLengthSid(token_buf->User.Sid);
- PSID pSID = NEW_C_HEAP_ARRAY(char, nbytes);
+ PSID pSID = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal);
if (!CopySid(nbytes, pSID, token_buf->User.Sid)) {
if (PrintMiscellaneous && Verbose) {
warning("GetTokenInformation failure: lasterror = %d,"
" rsize = %d\n", GetLastError(), rsize);
}
- FREE_C_HEAP_ARRAY(char, token_buf);
- FREE_C_HEAP_ARRAY(char, pSID);
+ FREE_C_HEAP_ARRAY(char, token_buf, mtInternal);
+ FREE_C_HEAP_ARRAY(char, pSID, mtInternal);
CloseHandle(hAccessToken);
return NULL;
}
// close the access token.
CloseHandle(hAccessToken);
- FREE_C_HEAP_ARRAY(char, token_buf);
+ FREE_C_HEAP_ARRAY(char, token_buf, mtInternal);
return pSID;
}
@@ -912,13 +912,13 @@
}
// create the new ACL
- newACL = (PACL) NEW_C_HEAP_ARRAY(char, newACLsize);
+ newACL = (PACL) NEW_C_HEAP_ARRAY(char, newACLsize, mtInternal);
if (!InitializeAcl(newACL, newACLsize, ACL_REVISION)) {
if (PrintMiscellaneous && Verbose) {
warning("InitializeAcl failure: lasterror = %d \n", GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
@@ -931,7 +931,7 @@
if (PrintMiscellaneous && Verbose) {
warning("InitializeAcl failure: lasterror = %d \n", GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
if (((ACCESS_ALLOWED_ACE *)ace)->Header.AceFlags && INHERITED_ACE) {
@@ -958,7 +958,7 @@
if (PrintMiscellaneous && Verbose) {
warning("AddAce failure: lasterror = %d \n", GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
}
@@ -974,7 +974,7 @@
warning("AddAccessAllowedAce failure: lasterror = %d \n",
GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
}
@@ -989,7 +989,7 @@
if (PrintMiscellaneous && Verbose) {
warning("InitializeAcl failure: lasterror = %d \n", GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace,
@@ -997,7 +997,7 @@
if (PrintMiscellaneous && Verbose) {
warning("AddAce failure: lasterror = %d \n", GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
ace_index++;
@@ -1010,7 +1010,7 @@
warning("SetSecurityDescriptorDacl failure:"
" lasterror = %d \n", GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
@@ -1030,7 +1030,7 @@
warning("SetSecurityDescriptorControl failure:"
" lasterror = %d \n", GetLastError());
}
- FREE_C_HEAP_ARRAY(char, newACL);
+ FREE_C_HEAP_ARRAY(char, newACL, mtInternal);
return false;
}
}
@@ -1054,7 +1054,7 @@
// allocate space for a security descriptor
PSECURITY_DESCRIPTOR pSD = (PSECURITY_DESCRIPTOR)
- NEW_C_HEAP_ARRAY(char, SECURITY_DESCRIPTOR_MIN_LENGTH);
+ NEW_C_HEAP_ARRAY(char, SECURITY_DESCRIPTOR_MIN_LENGTH, mtInternal);
// initialize the security descriptor
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
@@ -1076,7 +1076,7 @@
// return it to the caller.
//
LPSECURITY_ATTRIBUTES lpSA = (LPSECURITY_ATTRIBUTES)
- NEW_C_HEAP_ARRAY(char, sizeof(SECURITY_ATTRIBUTES));
+ NEW_C_HEAP_ARRAY(char, sizeof(SECURITY_ATTRIBUTES), mtInternal);
lpSA->nLength = sizeof(SECURITY_ATTRIBUTES);
lpSA->lpSecurityDescriptor = pSD;
lpSA->bInheritHandle = FALSE;
@@ -1147,7 +1147,7 @@
// create a security attributes structure with access control
// entries as initialized above.
LPSECURITY_ATTRIBUTES lpSA = make_security_attr(aces, 3);
- FREE_C_HEAP_ARRAY(char, aces[0].pSid);
+ FREE_C_HEAP_ARRAY(char, aces[0].pSid, mtInternal);
FreeSid(everybodySid);
FreeSid(administratorsSid);
return(lpSA);
@@ -1462,15 +1462,15 @@
assert(((size != 0) && (size % os::vm_page_size() == 0)),
"unexpected PerfMemry region size");
- FREE_C_HEAP_ARRAY(char, user);
+ FREE_C_HEAP_ARRAY(char, user, mtInternal);
// create the shared memory resources
sharedmem_fileMapHandle =
create_sharedmem_resources(dirname, filename, objectname, size);
- FREE_C_HEAP_ARRAY(char, filename);
- FREE_C_HEAP_ARRAY(char, objectname);
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+ FREE_C_HEAP_ARRAY(char, objectname, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
if (sharedmem_fileMapHandle == NULL) {
return NULL;
@@ -1621,7 +1621,7 @@
// store file, we also don't following them when attaching
//
if (!is_directory_secure(dirname)) {
- FREE_C_HEAP_ARRAY(char, dirname);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
"Process not found");
}
@@ -1640,10 +1640,10 @@
strcpy(robjectname, objectname);
// free the c heap resources that are no longer needed
- if (luser != user) FREE_C_HEAP_ARRAY(char, luser);
- FREE_C_HEAP_ARRAY(char, dirname);
- FREE_C_HEAP_ARRAY(char, filename);
- FREE_C_HEAP_ARRAY(char, objectname);
+ if (luser != user) FREE_C_HEAP_ARRAY(char, luser, mtInternal);
+ FREE_C_HEAP_ARRAY(char, dirname, mtInternal);
+ FREE_C_HEAP_ARRAY(char, filename, mtInternal);
+ FREE_C_HEAP_ARRAY(char, objectname, mtInternal);
if (*sizep == 0) {
size = sharedmem_filesize(rfilename, CHECK);
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -261,7 +261,7 @@
GrowableArray<int>* CodeBuffer::create_patch_overflow() {
if (_overflow_arena == NULL) {
- _overflow_arena = new Arena();
+ _overflow_arena = new (mtCode) Arena();
}
return new (_overflow_arena) GrowableArray<int>(_overflow_arena, 8, 0, 0);
}
@@ -910,7 +910,7 @@
_comments.add_comment(offset, comment);
}
-class CodeComment: public CHeapObj {
+class CodeComment: public CHeapObj<mtCode> {
private:
friend class CodeComments;
intptr_t _offset;
@@ -919,13 +919,13 @@
~CodeComment() {
assert(_next == NULL, "wrong interface for freeing list");
- os::free((void*)_comment);
+ os::free((void*)_comment, mtCode);
}
public:
CodeComment(intptr_t offset, const char * comment) {
_offset = offset;
- _comment = os::strdup(comment);
+ _comment = os::strdup(comment, mtCode);
_next = NULL;
}
--- a/hotspot/src/share/vm/c1/c1_CFGPrinter.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/c1/c1_CFGPrinter.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,7 +33,7 @@
#ifndef PRODUCT
-class CFGPrinterOutput : public CHeapObj {
+class CFGPrinterOutput : public CHeapObj<mtCompiler> {
private:
outputStream* _output;
@@ -106,7 +106,7 @@
CFGPrinterOutput::CFGPrinterOutput()
- : _output(new(ResourceObj::C_HEAP) fileStream("output.cfg"))
+ : _output(new(ResourceObj::C_HEAP, mtCompiler) fileStream("output.cfg"))
{
}
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -55,7 +55,7 @@
void Compiler::initialize_all() {
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
- Arena* arena = new Arena();
+ Arena* arena = new (mtCompiler) Arena();
Runtime1::initialize(buffer_blob);
FrameMap::initialize();
// initialize data structures
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -2467,12 +2467,12 @@
// Allocate them with new so they are never destroyed (otherwise, a
// forced exit could destroy these objects while they are still in
// use).
-ConstantOopWriteValue* LinearScan::_oop_null_scope_value = new (ResourceObj::C_HEAP) ConstantOopWriteValue(NULL);
-ConstantIntValue* LinearScan::_int_m1_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(-1);
-ConstantIntValue* LinearScan::_int_0_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(0);
-ConstantIntValue* LinearScan::_int_1_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(1);
-ConstantIntValue* LinearScan::_int_2_scope_value = new (ResourceObj::C_HEAP) ConstantIntValue(2);
-LocationValue* _illegal_value = new (ResourceObj::C_HEAP) LocationValue(Location());
+ConstantOopWriteValue* LinearScan::_oop_null_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantOopWriteValue(NULL);
+ConstantIntValue* LinearScan::_int_m1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(-1);
+ConstantIntValue* LinearScan::_int_0_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(0);
+ConstantIntValue* LinearScan::_int_1_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(1);
+ConstantIntValue* LinearScan::_int_2_scope_value = new (ResourceObj::C_HEAP, mtCompiler) ConstantIntValue(2);
+LocationValue* _illegal_value = new (ResourceObj::C_HEAP, mtCompiler) LocationValue(Location());
void LinearScan::init_compute_debug_info() {
// cache for frequently used scope values
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -111,7 +111,7 @@
// This Arena is long lived and exists in the resource mark of the
// compiler thread that initializes the initial ciObjectFactory which
// creates the shared ciObjects that all later ciObjectFactories use.
- Arena* arena = new Arena();
+ Arena* arena = new (mtCompiler) Arena();
ciEnv initial(arena);
ciEnv* env = ciEnv::current();
env->_factory->init_shared_objects();
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1368,7 +1368,7 @@
};
-class LVT_Hash: public CHeapObj {
+class LVT_Hash: public CHeapObj<mtClass> {
public:
LocalVariableTableElement *_elem; // element
LVT_Hash* _next; // Next entry in hash table
@@ -2337,12 +2337,7 @@
// Don't bother storing it if there is no way to retrieve it
if (JvmtiExport::can_get_source_debug_extension()) {
- // Optimistically assume that only 1 byte UTF format is used
- // (common case)
- TempNewSymbol sde_symbol = SymbolTable::new_symbol((const char*)sde_buffer, length, CHECK);
- k->set_source_debug_extension(sde_symbol);
- // Note that set_source_debug_extension() increments the reference count
- // for its copy of the Symbol*, so use a TempNewSymbol here.
+ k->set_source_debug_extension((char*)sde_buffer, length);
}
// Got utf8 string, set stream position forward
cfs->skip_u1(length, CHECK);
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -153,7 +153,7 @@
_meta_package_names = NULL;
_num_meta_package_names = 0;
} else {
- _meta_package_names = NEW_C_HEAP_ARRAY(char*, num_meta_package_names);
+ _meta_package_names = NEW_C_HEAP_ARRAY(char*, num_meta_package_names, mtClass);
_num_meta_package_names = num_meta_package_names;
memcpy(_meta_package_names, meta_package_names, num_meta_package_names * sizeof(char*));
}
@@ -161,7 +161,7 @@
MetaIndex::~MetaIndex() {
- FREE_C_HEAP_ARRAY(char*, _meta_package_names);
+ FREE_C_HEAP_ARRAY(char*, _meta_package_names, mtClass);
}
@@ -192,7 +192,7 @@
}
ClassPathDirEntry::ClassPathDirEntry(char* dir) : ClassPathEntry() {
- _dir = NEW_C_HEAP_ARRAY(char, strlen(dir)+1);
+ _dir = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
strcpy(_dir, dir);
}
@@ -229,7 +229,7 @@
ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() {
_zip = zip;
- _zip_name = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1);
+ _zip_name = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
strcpy(_zip_name, zip_name);
}
@@ -237,7 +237,7 @@
if (ZipClose != NULL) {
(*ZipClose)(_zip);
}
- FREE_C_HEAP_ARRAY(char, _zip_name);
+ FREE_C_HEAP_ARRAY(char, _zip_name, mtClass);
}
ClassFileStream* ClassPathZipEntry::open_stream(const char* name) {
@@ -454,11 +454,11 @@
while (sys_class_path[end] && sys_class_path[end] != os::path_separator()[0]) {
end++;
}
- char* path = NEW_C_HEAP_ARRAY(char, end-start+1);
+ char* path = NEW_C_HEAP_ARRAY(char, end-start+1, mtClass);
strncpy(path, &sys_class_path[start], end-start);
path[end-start] = '\0';
update_class_path_entry_list(path, false);
- FREE_C_HEAP_ARRAY(char, path);
+ FREE_C_HEAP_ARRAY(char, path, mtClass);
while (sys_class_path[end] == os::path_separator()[0]) {
end++;
}
@@ -652,13 +652,13 @@
// in the classpath must be the same files, in the same order, even
// though the exact name is not the same.
-class PackageInfo: public BasicHashtableEntry {
+class PackageInfo: public BasicHashtableEntry<mtClass> {
public:
const char* _pkgname; // Package name
int _classpath_index; // Index of directory or JAR file loaded from
PackageInfo* next() {
- return (PackageInfo*)BasicHashtableEntry::next();
+ return (PackageInfo*)BasicHashtableEntry<mtClass>::next();
}
const char* pkgname() { return _pkgname; }
@@ -674,7 +674,7 @@
};
-class PackageHashtable : public BasicHashtable {
+class PackageHashtable : public BasicHashtable<mtClass> {
private:
inline unsigned int compute_hash(const char *s, int n) {
unsigned int val = 0;
@@ -685,7 +685,7 @@
}
PackageInfo* bucket(int index) {
- return (PackageInfo*)BasicHashtable::bucket(index);
+ return (PackageInfo*)BasicHashtable<mtClass>::bucket(index);
}
PackageInfo* get_entry(int index, unsigned int hash,
@@ -702,10 +702,10 @@
public:
PackageHashtable(int table_size)
- : BasicHashtable(table_size, sizeof(PackageInfo)) {}
+ : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo)) {}
- PackageHashtable(int table_size, HashtableBucket* t, int number_of_entries)
- : BasicHashtable(table_size, sizeof(PackageInfo), t, number_of_entries) {}
+ PackageHashtable(int table_size, HashtableBucket<mtClass>* t, int number_of_entries)
+ : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo), t, number_of_entries) {}
PackageInfo* get_entry(const char* pkgname, int n) {
unsigned int hash = compute_hash(pkgname, n);
@@ -715,14 +715,14 @@
PackageInfo* new_entry(char* pkgname, int n) {
unsigned int hash = compute_hash(pkgname, n);
PackageInfo* pp;
- pp = (PackageInfo*)BasicHashtable::new_entry(hash);
+ pp = (PackageInfo*)BasicHashtable<mtClass>::new_entry(hash);
pp->set_pkgname(pkgname);
return pp;
}
void add_entry(PackageInfo* pp) {
int index = hash_to_index(pp->hash());
- BasicHashtable::add_entry(index, pp);
+ BasicHashtable<mtClass>::add_entry(index, pp);
}
void copy_pkgnames(const char** packages) {
@@ -742,7 +742,7 @@
void PackageHashtable::copy_table(char** top, char* end,
PackageHashtable* table) {
// Copy (relocate) the table to the shared space.
- BasicHashtable::copy_table(top, end);
+ BasicHashtable<mtClass>::copy_table(top, end);
// Calculate the space needed for the package name strings.
int i;
@@ -815,7 +815,7 @@
// Package prefix found
int n = cp - pkgname + 1;
- char* new_pkgname = NEW_C_HEAP_ARRAY(char, n + 1);
+ char* new_pkgname = NEW_C_HEAP_ARRAY(char, n + 1, mtClass);
if (new_pkgname == NULL) {
return false;
}
@@ -929,10 +929,10 @@
}
-void ClassLoader::create_package_info_table(HashtableBucket *t, int length,
+void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int length,
int number_of_entries) {
assert(_package_hash_table == NULL, "One package info table allowed.");
- assert(length == package_hash_table_size * sizeof(HashtableBucket),
+ assert(length == package_hash_table_size * sizeof(HashtableBucket<mtClass>),
"bad shared package info size.");
_package_hash_table = new PackageHashtable(package_hash_table_size, t,
number_of_entries);
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,7 +33,7 @@
// Meta-index (optional, to be able to skip opening boot classpath jar files)
-class MetaIndex: public CHeapObj {
+class MetaIndex: public CHeapObj<mtClass> {
private:
char** _meta_package_names;
int _num_meta_package_names;
@@ -46,7 +46,7 @@
// Class path entry (directory or zip file)
-class ClassPathEntry: public CHeapObj {
+class ClassPathEntry: public CHeapObj<mtClass> {
private:
ClassPathEntry* _next;
public:
@@ -141,7 +141,7 @@
class PackageHashtable;
class PackageInfo;
-class HashtableBucket;
+template <MEMFLAGS F> class HashtableBucket;
class ClassLoader: AllStatic {
public:
@@ -299,7 +299,7 @@
// Initialization
static void initialize();
static void create_package_info_table();
- static void create_package_info_table(HashtableBucket *t, int length,
+ static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
int number_of_entries);
static int compute_Object_vtable();
--- a/hotspot/src/share/vm/classfile/dictionary.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,16 +36,16 @@
Dictionary::Dictionary(int table_size)
- : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry)) {
+ : TwoOopHashtable<klassOop, mtClass>(table_size, sizeof(DictionaryEntry)) {
_current_class_index = 0;
_current_class_entry = NULL;
};
-Dictionary::Dictionary(int table_size, HashtableBucket* t,
+Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
int number_of_entries)
- : TwoOopHashtable<klassOop>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
+ : TwoOopHashtable<klassOop, mtClass>(table_size, sizeof(DictionaryEntry), t, number_of_entries) {
_current_class_index = 0;
_current_class_entry = NULL;
};
@@ -54,7 +54,7 @@
DictionaryEntry* Dictionary::new_entry(unsigned int hash, klassOop klass,
oop loader) {
DictionaryEntry* entry;
- entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(hash, klass);
+ entry = (DictionaryEntry*)Hashtable<klassOop, mtClass>::new_entry(hash, klass);
entry->set_loader(loader);
entry->set_pd_set(NULL);
return entry;
@@ -62,7 +62,7 @@
DictionaryEntry* Dictionary::new_entry() {
- DictionaryEntry* entry = (DictionaryEntry*)Hashtable<klassOop>::new_entry(0L, NULL);
+ DictionaryEntry* entry = (DictionaryEntry*)Hashtable<klassOop, mtClass>::new_entry(0L, NULL);
entry->set_loader(NULL);
entry->set_pd_set(NULL);
return entry;
@@ -76,7 +76,7 @@
entry->set_pd_set(to_delete->next());
delete to_delete;
}
- Hashtable<klassOop>::free_entry(entry);
+ Hashtable<klassOop, mtClass>::free_entry(entry);
}
@@ -554,12 +554,12 @@
}
SymbolPropertyTable::SymbolPropertyTable(int table_size)
- : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry))
+ : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
{
}
-SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket* t,
+SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t,
int number_of_entries)
- : Hashtable<Symbol*>(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
+ : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
{
}
@@ -584,7 +584,7 @@
assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry");
SymbolPropertyEntry* p = new_entry(hash, sym, sym_mode);
- Hashtable<Symbol*>::add_entry(index, p);
+ Hashtable<Symbol*, mtSymbol>::add_entry(index, p);
return p;
}
--- a/hotspot/src/share/vm/classfile/dictionary.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/dictionary.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,7 +36,7 @@
// The data structure for the system dictionary (and the shared system
// dictionary).
-class Dictionary : public TwoOopHashtable<klassOop> {
+class Dictionary : public TwoOopHashtable<klassOop, mtClass> {
friend class VMStructs;
private:
// current iteration index.
@@ -48,22 +48,22 @@
Symbol* name, Handle loader);
DictionaryEntry* bucket(int i) {
- return (DictionaryEntry*)Hashtable<klassOop>::bucket(i);
+ return (DictionaryEntry*)Hashtable<klassOop, mtClass>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
DictionaryEntry** bucket_addr(int i) {
- return (DictionaryEntry**)Hashtable<klassOop>::bucket_addr(i);
+ return (DictionaryEntry**)Hashtable<klassOop, mtClass>::bucket_addr(i);
}
void add_entry(int index, DictionaryEntry* new_entry) {
- Hashtable<klassOop>::add_entry(index, (HashtableEntry<oop>*)new_entry);
+ Hashtable<klassOop, mtClass>::add_entry(index, (HashtableEntry<oop, mtClass>*)new_entry);
}
public:
Dictionary(int table_size);
- Dictionary(int table_size, HashtableBucket* t, int number_of_entries);
+ Dictionary(int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
DictionaryEntry* new_entry(unsigned int hash, klassOop klass, oop loader);
@@ -129,7 +129,7 @@
// The following classes can be in dictionary.cpp, but we need these
// to be in header file so that SA's vmStructs can access.
-class ProtectionDomainEntry :public CHeapObj {
+class ProtectionDomainEntry :public CHeapObj<mtClass> {
friend class VMStructs;
public:
ProtectionDomainEntry* _next;
@@ -147,7 +147,7 @@
// An entry in the system dictionary, this describes a class as
// { klassOop, loader, protection_domain }.
-class DictionaryEntry : public HashtableEntry<klassOop> {
+class DictionaryEntry : public HashtableEntry<klassOop, mtClass> {
friend class VMStructs;
private:
// Contains the set of approved protection domains that can access
@@ -166,11 +166,11 @@
klassOop* klass_addr() { return (klassOop*)literal_addr(); }
DictionaryEntry* next() const {
- return (DictionaryEntry*)HashtableEntry<klassOop>::next();
+ return (DictionaryEntry*)HashtableEntry<klassOop, mtClass>::next();
}
DictionaryEntry** next_addr() {
- return (DictionaryEntry**)HashtableEntry<klassOop>::next_addr();
+ return (DictionaryEntry**)HashtableEntry<klassOop, mtClass>::next_addr();
}
oop loader() const { return _loader; }
@@ -228,7 +228,7 @@
// Entry in a SymbolPropertyTable, mapping a single Symbol*
// to a managed and an unmanaged pointer.
-class SymbolPropertyEntry : public HashtableEntry<Symbol*> {
+class SymbolPropertyEntry : public HashtableEntry<Symbol*, mtSymbol> {
friend class VMStructs;
private:
intptr_t _symbol_mode; // secondary key
@@ -248,11 +248,11 @@
void set_property_data(address p) { _property_data = p; }
SymbolPropertyEntry* next() const {
- return (SymbolPropertyEntry*)HashtableEntry<Symbol*>::next();
+ return (SymbolPropertyEntry*)HashtableEntry<Symbol*, mtSymbol>::next();
}
SymbolPropertyEntry** next_addr() {
- return (SymbolPropertyEntry**)HashtableEntry<Symbol*>::next_addr();
+ return (SymbolPropertyEntry**)HashtableEntry<Symbol*, mtSymbol>::next_addr();
}
oop* property_oop_addr() { return &_property_oop; }
@@ -278,16 +278,16 @@
// A system-internal mapping of symbols to pointers, both managed
// and unmanaged. Used to record the auto-generation of each method
// MethodHandle.invoke(S)T, for all signatures (S)T.
-class SymbolPropertyTable : public Hashtable<Symbol*> {
+class SymbolPropertyTable : public Hashtable<Symbol*, mtSymbol> {
friend class VMStructs;
private:
SymbolPropertyEntry* bucket(int i) {
- return (SymbolPropertyEntry*) Hashtable<Symbol*>::bucket(i);
+ return (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
SymbolPropertyEntry** bucket_addr(int i) {
- return (SymbolPropertyEntry**) Hashtable<Symbol*>::bucket_addr(i);
+ return (SymbolPropertyEntry**) Hashtable<Symbol*, mtSymbol>::bucket_addr(i);
}
void add_entry(int index, SymbolPropertyEntry* new_entry) {
@@ -298,7 +298,7 @@
}
SymbolPropertyEntry* new_entry(unsigned int hash, Symbol* symbol, intptr_t symbol_mode) {
- SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable<Symbol*>::new_entry(hash, symbol);
+ SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::new_entry(hash, symbol);
// Hashtable with Symbol* literal must increment and decrement refcount.
symbol->increment_refcount();
entry->set_symbol_mode(symbol_mode);
@@ -309,17 +309,17 @@
public:
SymbolPropertyTable(int table_size);
- SymbolPropertyTable(int table_size, HashtableBucket* t, int number_of_entries);
+ SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t, int number_of_entries);
void free_entry(SymbolPropertyEntry* entry) {
// decrement Symbol refcount here because hashtable doesn't.
entry->literal()->decrement_refcount();
- Hashtable<Symbol*>::free_entry(entry);
+ Hashtable<Symbol*, mtSymbol>::free_entry(entry);
}
unsigned int compute_hash(Symbol* sym, intptr_t symbol_mode) {
// Use the regular identity_hash.
- return Hashtable<Symbol*>::compute_hash(sym) ^ symbol_mode;
+ return Hashtable<Symbol*, mtSymbol>::compute_hash(sym) ^ symbol_mode;
}
int index_for(Symbol* name, intptr_t symbol_mode) {
--- a/hotspot/src/share/vm/classfile/javaAssertions.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/javaAssertions.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -58,7 +58,7 @@
// it is never freed, so will be leaked (along with other option strings -
// e.g., bootclasspath) if a process creates/destroys multiple VMs.
int len = (int)strlen(name);
- char *name_copy = NEW_C_HEAP_ARRAY(char, len + 1);
+ char *name_copy = NEW_C_HEAP_ARRAY(char, len + 1, mtClass);
strcpy(name_copy, name);
// Figure out which list the new item should go on. Names that end in "..."
--- a/hotspot/src/share/vm/classfile/javaAssertions.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/javaAssertions.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -68,7 +68,7 @@
static OptionList* _packages; // Options for package trees.
};
-class JavaAssertions::OptionList: public CHeapObj {
+class JavaAssertions::OptionList: public CHeapObj<mtClass> {
public:
inline OptionList(const char* name, bool enable, OptionList* next);
--- a/hotspot/src/share/vm/classfile/loaderConstraints.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -31,7 +31,7 @@
#include "utilities/hashtable.inline.hpp"
LoaderConstraintTable::LoaderConstraintTable(int nof_buckets)
- : Hashtable<klassOop>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
+ : Hashtable<klassOop, mtClass>(nof_buckets, sizeof(LoaderConstraintEntry)) {};
LoaderConstraintEntry* LoaderConstraintTable::new_entry(
@@ -39,7 +39,7 @@
klassOop klass, int num_loaders,
int max_loaders) {
LoaderConstraintEntry* entry;
- entry = (LoaderConstraintEntry*)Hashtable<klassOop>::new_entry(hash, klass);
+ entry = (LoaderConstraintEntry*)Hashtable<klassOop, mtClass>::new_entry(hash, klass);
entry->set_name(name);
entry->set_num_loaders(num_loaders);
entry->set_max_loaders(max_loaders);
@@ -49,7 +49,7 @@
void LoaderConstraintTable::free_entry(LoaderConstraintEntry *entry) {
// decrement name refcount before freeing
entry->name()->decrement_refcount();
- Hashtable<klassOop>::free_entry(entry);
+ Hashtable<klassOop, mtClass>::free_entry(entry);
}
@@ -164,7 +164,7 @@
// Purge entry
*p = probe->next();
- FREE_C_HEAP_ARRAY(oop, probe->loaders());
+ FREE_C_HEAP_ARRAY(oop, probe->loaders(), mtClass);
free_entry(probe);
} else {
#ifdef ASSERT
@@ -224,7 +224,7 @@
int index = hash_to_index(hash);
LoaderConstraintEntry* p;
p = new_entry(hash, class_name, klass, 2, 2);
- p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2));
+ p->set_loaders(NEW_C_HEAP_ARRAY(oop, 2, mtClass));
p->set_loader(0, class_loader1());
p->set_loader(1, class_loader2());
p->set_klass(klass);
@@ -340,10 +340,10 @@
int nfree) {
if (p->max_loaders() - p->num_loaders() < nfree) {
int n = nfree + p->num_loaders();
- oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n);
+ oop* new_loaders = NEW_C_HEAP_ARRAY(oop, n, mtClass);
memcpy(new_loaders, p->loaders(), sizeof(oop) * p->num_loaders());
p->set_max_loaders(n);
- FREE_C_HEAP_ARRAY(oop, p->loaders());
+ FREE_C_HEAP_ARRAY(oop, p->loaders(), mtClass);
p->set_loaders(new_loaders);
}
}
@@ -425,7 +425,7 @@
}
*pp2 = p2->next();
- FREE_C_HEAP_ARRAY(oop, p2->loaders());
+ FREE_C_HEAP_ARRAY(oop, p2->loaders(), mtClass);
free_entry(p2);
return;
}
--- a/hotspot/src/share/vm/classfile/loaderConstraints.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/loaderConstraints.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -31,7 +31,7 @@
class LoaderConstraintEntry;
-class LoaderConstraintTable : public Hashtable<klassOop> {
+class LoaderConstraintTable : public Hashtable<klassOop, mtClass> {
friend class VMStructs;
private:
@@ -53,11 +53,11 @@
void free_entry(LoaderConstraintEntry *entry);
LoaderConstraintEntry* bucket(int i) {
- return (LoaderConstraintEntry*)Hashtable<klassOop>::bucket(i);
+ return (LoaderConstraintEntry*)Hashtable<klassOop, mtClass>::bucket(i);
}
LoaderConstraintEntry** bucket_addr(int i) {
- return (LoaderConstraintEntry**)Hashtable<klassOop>::bucket_addr(i);
+ return (LoaderConstraintEntry**)Hashtable<klassOop, mtClass>::bucket_addr(i);
}
// GC support
@@ -94,7 +94,7 @@
#endif
};
-class LoaderConstraintEntry : public HashtableEntry<klassOop> {
+class LoaderConstraintEntry : public HashtableEntry<klassOop, mtClass> {
friend class VMStructs;
private:
Symbol* _name; // class name
@@ -109,14 +109,14 @@
void set_klass(klassOop k) { set_literal(k); }
LoaderConstraintEntry* next() {
- return (LoaderConstraintEntry*)HashtableEntry<klassOop>::next();
+ return (LoaderConstraintEntry*)HashtableEntry<klassOop, mtClass>::next();
}
LoaderConstraintEntry** next_addr() {
- return (LoaderConstraintEntry**)HashtableEntry<klassOop>::next_addr();
+ return (LoaderConstraintEntry**)HashtableEntry<klassOop, mtClass>::next_addr();
}
void set_next(LoaderConstraintEntry* next) {
- HashtableEntry<klassOop>::set_next(next);
+ HashtableEntry<klassOop, mtClass>::set_next(next);
}
Symbol* name() { return _name; }
--- a/hotspot/src/share/vm/classfile/placeholders.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/placeholders.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
PlaceholderEntry* PlaceholderTable::new_entry(int hash, Symbol* name,
oop loader, bool havesupername,
Symbol* supername) {
- PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable<Symbol*>::new_entry(hash, name);
+ PlaceholderEntry* entry = (PlaceholderEntry*)Hashtable<Symbol*, mtClass>::new_entry(hash, name);
// Hashtable with Symbol* literal must increment and decrement refcount.
name->increment_refcount();
entry->set_loader(loader);
@@ -52,7 +52,7 @@
// decrement Symbol refcount here because Hashtable doesn't.
entry->literal()->decrement_refcount();
if (entry->supername() != NULL) entry->supername()->decrement_refcount();
- Hashtable<Symbol*>::free_entry(entry);
+ Hashtable<Symbol*, mtClass>::free_entry(entry);
}
@@ -166,7 +166,7 @@
}
PlaceholderTable::PlaceholderTable(int table_size)
- : TwoOopHashtable<Symbol*>(table_size, sizeof(PlaceholderEntry)) {
+ : TwoOopHashtable<Symbol*, mtClass>(table_size, sizeof(PlaceholderEntry)) {
}
--- a/hotspot/src/share/vm/classfile/placeholders.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/placeholders.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
// being loaded, as well as arrays of primitives.
//
-class PlaceholderTable : public TwoOopHashtable<Symbol*> {
+class PlaceholderTable : public TwoOopHashtable<Symbol*, mtClass> {
friend class VMStructs;
public:
@@ -44,15 +44,15 @@
void free_entry(PlaceholderEntry* entry);
PlaceholderEntry* bucket(int i) {
- return (PlaceholderEntry*)Hashtable<Symbol*>::bucket(i);
+ return (PlaceholderEntry*)Hashtable<Symbol*, mtClass>::bucket(i);
}
PlaceholderEntry** bucket_addr(int i) {
- return (PlaceholderEntry**)Hashtable<Symbol*>::bucket_addr(i);
+ return (PlaceholderEntry**)Hashtable<Symbol*, mtClass>::bucket_addr(i);
}
void add_entry(int index, PlaceholderEntry* new_entry) {
- Hashtable<Symbol*>::add_entry(index, (HashtableEntry<Symbol*>*)new_entry);
+ Hashtable<Symbol*, mtClass>::add_entry(index, (HashtableEntry<Symbol*, mtClass>*)new_entry);
}
void add_entry(int index, unsigned int hash, Symbol* name,
@@ -116,7 +116,7 @@
// For DEFINE_CLASS, the head of the queue owns the
// define token and the rest of the threads wait to return the
// result the first thread gets.
-class SeenThread: public CHeapObj {
+class SeenThread: public CHeapObj<mtInternal> {
private:
Thread *_thread;
SeenThread* _stnext;
@@ -152,7 +152,7 @@
// on store ordering here.
// The system dictionary is the only user of this class.
-class PlaceholderEntry : public HashtableEntry<Symbol*> {
+class PlaceholderEntry : public HashtableEntry<Symbol*, mtClass> {
friend class VMStructs;
@@ -206,11 +206,11 @@
void set_defineThreadQ(SeenThread* SeenThread) { _defineThreadQ = SeenThread; }
PlaceholderEntry* next() const {
- return (PlaceholderEntry*)HashtableEntry<Symbol*>::next();
+ return (PlaceholderEntry*)HashtableEntry<Symbol*, mtClass>::next();
}
PlaceholderEntry** next_addr() {
- return (PlaceholderEntry**)HashtableEntry<Symbol*>::next_addr();
+ return (PlaceholderEntry**)HashtableEntry<Symbol*, mtClass>::next_addr();
}
// Test for equality
--- a/hotspot/src/share/vm/classfile/resolutionErrors.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/resolutionErrors.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -67,7 +67,7 @@
ResolutionErrorEntry* ResolutionErrorTable::new_entry(int hash, constantPoolOop pool,
int cp_index, Symbol* error)
{
- ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<constantPoolOop>::new_entry(hash, pool);
+ ResolutionErrorEntry* entry = (ResolutionErrorEntry*)Hashtable<constantPoolOop, mtClass>::new_entry(hash, pool);
entry->set_cp_index(cp_index);
NOT_PRODUCT(entry->set_error(NULL);)
entry->set_error(error);
@@ -79,13 +79,13 @@
// decrement error refcount
assert(entry->error() != NULL, "error should be set");
entry->error()->decrement_refcount();
- Hashtable<constantPoolOop>::free_entry(entry);
+ Hashtable<constantPoolOop, mtClass>::free_entry(entry);
}
// create resolution error table
ResolutionErrorTable::ResolutionErrorTable(int table_size)
- : Hashtable<constantPoolOop>(table_size, sizeof(ResolutionErrorEntry)) {
+ : Hashtable<constantPoolOop, mtClass>(table_size, sizeof(ResolutionErrorEntry)) {
}
// GC support
--- a/hotspot/src/share/vm/classfile/resolutionErrors.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/resolutionErrors.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,7 +33,7 @@
// ResolutionError objects are used to record errors encountered during
// constant pool resolution (JVMS 5.4.3).
-class ResolutionErrorTable : public Hashtable<constantPoolOop> {
+class ResolutionErrorTable : public Hashtable<constantPoolOop, mtClass> {
public:
ResolutionErrorTable(int table_size);
@@ -42,15 +42,16 @@
void free_entry(ResolutionErrorEntry *entry);
ResolutionErrorEntry* bucket(int i) {
- return (ResolutionErrorEntry*)Hashtable<constantPoolOop>::bucket(i);
+ return (ResolutionErrorEntry*)Hashtable<constantPoolOop, mtClass>::bucket(i);
}
ResolutionErrorEntry** bucket_addr(int i) {
- return (ResolutionErrorEntry**)Hashtable<constantPoolOop>::bucket_addr(i);
+ return (ResolutionErrorEntry**)Hashtable<constantPoolOop, mtClass>::bucket_addr(i);
}
void add_entry(int index, ResolutionErrorEntry* new_entry) {
- Hashtable<constantPoolOop>::add_entry(index, (HashtableEntry<constantPoolOop>*)new_entry);
+ Hashtable<constantPoolOop, mtClass>::add_entry(index,
+ (HashtableEntry<constantPoolOop, mtClass>*)new_entry);
}
void add_entry(int index, unsigned int hash,
@@ -74,7 +75,7 @@
};
-class ResolutionErrorEntry : public HashtableEntry<constantPoolOop> {
+class ResolutionErrorEntry : public HashtableEntry<constantPoolOop, mtClass> {
private:
int _cp_index;
Symbol* _error;
@@ -90,11 +91,11 @@
void set_error(Symbol* e);
ResolutionErrorEntry* next() const {
- return (ResolutionErrorEntry*)HashtableEntry<constantPoolOop>::next();
+ return (ResolutionErrorEntry*)HashtableEntry<constantPoolOop, mtClass>::next();
}
ResolutionErrorEntry** next_addr() {
- return (ResolutionErrorEntry**)HashtableEntry<constantPoolOop>::next_addr();
+ return (ResolutionErrorEntry**)HashtableEntry<constantPoolOop, mtClass>::next_addr();
}
// GC support
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -43,7 +43,6 @@
// Static arena for symbols that are not deallocated
Arena* SymbolTable::_arena = NULL;
bool SymbolTable::_needs_rehashing = false;
-jint SymbolTable::_seed = 0;
Symbol* SymbolTable::allocate_symbol(const u1* name, int len, bool c_heap, TRAPS) {
assert (len <= Symbol::max_length(), "should be checked by caller");
@@ -64,9 +63,9 @@
void SymbolTable::initialize_symbols(int arena_alloc_size) {
// Initialize the arena for global symbols, size passed in depends on CDS.
if (arena_alloc_size == 0) {
- _arena = new Arena();
+ _arena = new (mtSymbol) Arena();
} else {
- _arena = new Arena(arena_alloc_size);
+ _arena = new (mtSymbol) Arena(arena_alloc_size);
}
}
@@ -74,7 +73,7 @@
void SymbolTable::symbols_do(SymbolClosure *cl) {
const int n = the_table()->table_size();
for (int i = 0; i < n; i++) {
- for (HashtableEntry<Symbol*>* p = the_table()->bucket(i);
+ for (HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
p != NULL;
p = p->next()) {
cl->do_symbol(p->literal_addr());
@@ -92,8 +91,8 @@
int total = 0;
size_t memory_total = 0;
for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i);
- HashtableEntry<Symbol*>* entry = the_table()->bucket(i);
+ HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i);
+ HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i);
while (entry != NULL) {
// Shared entries are normally at the end of the bucket and if we run into
// a shared entry, then there is nothing more to remove. However, if we
@@ -117,7 +116,7 @@
p = entry->next_addr();
}
// get next entry
- entry = (HashtableEntry<Symbol*>*)HashtableEntry<Symbol*>::make_ptr(*p);
+ entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p);
}
}
symbols_removed += removed;
@@ -130,12 +129,6 @@
}
}
-unsigned int SymbolTable::new_hash(Symbol* sym) {
- ResourceMark rm;
- // Use alternate hashing algorithm on this symbol.
- return AltHashing::murmur3_32(seed(), (const jbyte*)sym->as_C_string(), sym->utf8_length());
-}
-
// Create a new table and using alternate hash code, populate the new table
// with the existing strings. Set flag to use the alternate hash code afterwards.
void SymbolTable::rehash_table() {
@@ -145,10 +138,6 @@
// Create a new symbol table
SymbolTable* new_table = new SymbolTable();
- // Initialize the global seed for hashing.
- _seed = AltHashing::compute_seed();
- assert(seed() != 0, "shouldn't be zero");
-
the_table()->move_to(new_table);
// Delete the table and buckets (entries are reused in new table).
@@ -164,7 +153,7 @@
Symbol* SymbolTable::lookup(int index, const char* name,
int len, unsigned int hash) {
int count = 0;
- for (HashtableEntry<Symbol*>* e = bucket(index); e != NULL; e = e->next()) {
+ for (HashtableEntry<Symbol*, mtSymbol>* e = bucket(index); e != NULL; e = e->next()) {
count++; // count all entries in this bucket, not just ones with same hash
if (e->hash() == hash) {
Symbol* sym = e->literal();
@@ -176,7 +165,7 @@
}
}
// If the bucket size is too deep check if this hash code is insufficient.
- if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
+ if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
_needs_rehashing = check_rehash_table(count);
}
return NULL;
@@ -268,7 +257,7 @@
unsigned int hash = hash_symbol((char*)sym->bytes(), sym->utf8_length());
int index = the_table()->hash_to_index(hash);
- for (HashtableEntry<Symbol*>* e = the_table()->bucket(index); e != NULL; e = e->next()) {
+ for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(index); e != NULL; e = e->next()) {
if (e->hash() == hash) {
Symbol* literal_sym = e->literal();
if (sym == literal_sym) {
@@ -387,7 +376,7 @@
Symbol* sym = allocate_symbol(name, len, c_heap, CHECK_NULL);
assert(sym->equals((char*)name, len), "symbol must be properly initialized");
- HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym);
+ HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
add_entry(index, entry);
return sym;
}
@@ -435,7 +424,7 @@
bool c_heap = class_loader() != NULL;
Symbol* sym = allocate_symbol((const u1*)names[i], lengths[i], c_heap, CHECK_(false));
assert(sym->equals(names[i], lengths[i]), "symbol must be properly initialized"); // why wouldn't it be???
- HashtableEntry<Symbol*>* entry = new_entry(hashValue, sym);
+ HashtableEntry<Symbol*, mtSymbol>* entry = new_entry(hashValue, sym);
add_entry(index, entry);
cp->symbol_at_put(cp_indices[i], sym);
}
@@ -446,7 +435,7 @@
void SymbolTable::verify() {
for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<Symbol*>* p = the_table()->bucket(i);
+ HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
Symbol* s = (Symbol*)(p->literal());
guarantee(s != NULL, "symbol is NULL");
@@ -462,7 +451,7 @@
NumberSeq summary;
for (int i = 0; i < the_table()->table_size(); ++i) {
int count = 0;
- for (HashtableEntry<Symbol*>* e = the_table()->bucket(i);
+ for (HashtableEntry<Symbol*, mtSymbol>* e = the_table()->bucket(i);
e != NULL; e = e->next()) {
count++;
}
@@ -499,7 +488,7 @@
int memory_total = 0;
int count = 0;
for (i = 0; i < the_table()->table_size(); i++) {
- HashtableEntry<Symbol*>* p = the_table()->bucket(i);
+ HashtableEntry<Symbol*, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
memory_total += p->literal()->object_size();
count++;
@@ -560,15 +549,15 @@
void SymbolTable::print() {
for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<Symbol*>** p = the_table()->bucket_addr(i);
- HashtableEntry<Symbol*>* entry = the_table()->bucket(i);
+ HashtableEntry<Symbol*, mtSymbol>** p = the_table()->bucket_addr(i);
+ HashtableEntry<Symbol*, mtSymbol>* entry = the_table()->bucket(i);
if (entry != NULL) {
while (entry != NULL) {
tty->print(PTR_FORMAT " ", entry->literal());
entry->literal()->print();
tty->print(" %d", entry->literal()->refcount());
p = entry->next_addr();
- entry = (HashtableEntry<Symbol*>*)HashtableEntry<Symbol*>::make_ptr(*p);
+ entry = (HashtableEntry<Symbol*, mtSymbol>*)HashtableEntry<Symbol*, mtSymbol>::make_ptr(*p);
}
tty->cr();
}
@@ -620,7 +609,6 @@
StringTable* StringTable::_the_table = NULL;
bool StringTable::_needs_rehashing = false;
-jint StringTable::_seed = 0;
// Pick hashing algorithm
unsigned int StringTable::hash_string(const jchar* s, int len) {
@@ -631,7 +619,7 @@
oop StringTable::lookup(int index, jchar* name,
int len, unsigned int hash) {
int count = 0;
- for (HashtableEntry<oop>* l = bucket(index); l != NULL; l = l->next()) {
+ for (HashtableEntry<oop, mtSymbol>* l = bucket(index); l != NULL; l = l->next()) {
count++;
if (l->hash() == hash) {
if (java_lang_String::equals(l->literal(), name, len)) {
@@ -640,7 +628,7 @@
}
}
// If the bucket size is too deep check if this hash code is insufficient.
- if (count >= BasicHashtable::rehash_count && !needs_rehashing()) {
+ if (count >= BasicHashtable<mtSymbol>::rehash_count && !needs_rehashing()) {
_needs_rehashing = check_rehash_table(count);
}
return NULL;
@@ -676,7 +664,7 @@
return test;
}
- HashtableEntry<oop>* entry = new_entry(hashValue, string());
+ HashtableEntry<oop, mtSymbol>* entry = new_entry(hashValue, string());
add_entry(index, entry);
return string();
}
@@ -761,8 +749,8 @@
// entries at a safepoint.
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<oop>** p = the_table()->bucket_addr(i);
- HashtableEntry<oop>* entry = the_table()->bucket(i);
+ HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
+ HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
while (entry != NULL) {
// Shared entries are normally at the end of the bucket and if we run into
// a shared entry, then there is nothing more to remove. However, if we
@@ -778,15 +766,15 @@
*p = entry->next();
the_table()->free_entry(entry);
}
- entry = (HashtableEntry<oop>*)HashtableEntry<oop>::make_ptr(*p);
+ entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p);
}
}
}
void StringTable::oops_do(OopClosure* f) {
for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<oop>** p = the_table()->bucket_addr(i);
- HashtableEntry<oop>* entry = the_table()->bucket(i);
+ HashtableEntry<oop, mtSymbol>** p = the_table()->bucket_addr(i);
+ HashtableEntry<oop, mtSymbol>* entry = the_table()->bucket(i);
while (entry != NULL) {
f->do_oop((oop*)entry->literal_addr());
@@ -798,14 +786,14 @@
} else {
p = entry->next_addr();
}
- entry = (HashtableEntry<oop>*)HashtableEntry<oop>::make_ptr(*p);
+ entry = (HashtableEntry<oop, mtSymbol>*)HashtableEntry<oop, mtSymbol>::make_ptr(*p);
}
}
}
void StringTable::verify() {
for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<oop>* p = the_table()->bucket(i);
+ HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
for ( ; p != NULL; p = p->next()) {
oop s = p->literal();
guarantee(s != NULL, "interned string is NULL");
@@ -821,7 +809,7 @@
void StringTable::dump(outputStream* st) {
NumberSeq summary;
for (int i = 0; i < the_table()->table_size(); ++i) {
- HashtableEntry<oop>* p = the_table()->bucket(i);
+ HashtableEntry<oop, mtSymbol>* p = the_table()->bucket(i);
int count = 0;
for ( ; p != NULL; p = p->next()) {
count++;
@@ -837,14 +825,6 @@
}
-unsigned int StringTable::new_hash(oop string) {
- ResourceMark rm;
- int length;
- jchar* chars = java_lang_String::as_unicode_string(string, length);
- // Use alternate hashing algorithm on the string
- return AltHashing::murmur3_32(seed(), chars, length);
-}
-
// Create a new table and using alternate hash code, populate the new table
// with the existing strings. Set flag to use the alternate hash code afterwards.
void StringTable::rehash_table() {
@@ -853,10 +833,6 @@
if (DumpSharedSpaces) return;
StringTable* new_table = new StringTable();
- // Initialize new global seed for hashing.
- _seed = AltHashing::compute_seed();
- assert(seed() != 0, "shouldn't be zero");
-
// Rehash the table
the_table()->move_to(new_table);
--- a/hotspot/src/share/vm/classfile/symbolTable.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/symbolTable.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -71,7 +71,7 @@
operator Symbol*() { return _temp; }
};
-class SymbolTable : public Hashtable<Symbol*> {
+class SymbolTable : public Hashtable<Symbol*, mtSymbol> {
friend class VMStructs;
friend class ClassFileParser;
@@ -81,7 +81,6 @@
// Set if one bucket is out of balance due to hash algorithm deficiency
static bool _needs_rehashing;
- static jint _seed;
// For statistics
static int symbols_removed;
@@ -113,10 +112,10 @@
Symbol* lookup(int index, const char* name, int len, unsigned int hash);
SymbolTable()
- : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>)) {}
+ : Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>)) {}
- SymbolTable(HashtableBucket* t, int number_of_entries)
- : Hashtable<Symbol*>(symbol_table_size, sizeof (HashtableEntry<Symbol*>), t,
+ SymbolTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
+ : Hashtable<Symbol*, mtSymbol>(symbol_table_size, sizeof (HashtableEntry<Symbol*, mtSymbol>), t,
number_of_entries) {}
// Arena for permanent symbols (null class loader) that are never unloaded
@@ -124,11 +123,6 @@
static Arena* arena() { return _arena; } // called for statistics
static void initialize_symbols(int arena_alloc_size = 0);
-
- static bool use_alternate_hashcode() { return _seed != 0; }
- static jint seed() { return _seed; }
-
- unsigned int new_hash(Symbol* sym);
public:
enum {
symbol_alloc_batch_size = 8,
@@ -145,10 +139,10 @@
initialize_symbols(symbol_alloc_arena_size);
}
- static void create_table(HashtableBucket* t, int length,
+ static void create_table(HashtableBucket<mtSymbol>* t, int length,
int number_of_entries) {
assert(_the_table == NULL, "One symbol table allowed.");
- assert(length == symbol_table_size * sizeof(HashtableBucket),
+ assert(length == symbol_table_size * sizeof(HashtableBucket<mtSymbol>),
"bad shared symbol size.");
_the_table = new SymbolTable(t, number_of_entries);
// if CDS give symbol table a default arena size since most symbols
@@ -224,13 +218,13 @@
// Sharing
static void copy_buckets(char** top, char*end) {
- the_table()->Hashtable<Symbol*>::copy_buckets(top, end);
+ the_table()->Hashtable<Symbol*, mtSymbol>::copy_buckets(top, end);
}
static void copy_table(char** top, char*end) {
- the_table()->Hashtable<Symbol*>::copy_table(top, end);
+ the_table()->Hashtable<Symbol*, mtSymbol>::copy_table(top, end);
}
static void reverse(void* boundary = NULL) {
- the_table()->Hashtable<Symbol*>::reverse(boundary);
+ the_table()->Hashtable<Symbol*, mtSymbol>::reverse(boundary);
}
// Rehash the symbol table if it gets out of balance
@@ -238,8 +232,7 @@
static bool needs_rehashing() { return _needs_rehashing; }
};
-
-class StringTable : public Hashtable<oop> {
+class StringTable : public Hashtable<oop, mtSymbol> {
friend class VMStructs;
private:
@@ -248,7 +241,6 @@
// Set if one bucket is out of balance due to hash algorithm deficiency
static bool _needs_rehashing;
- static jint _seed;
static oop intern(Handle string_or_null, jchar* chars, int length, TRAPS);
oop basic_add(int index, Handle string_or_null, jchar* name, int len,
@@ -256,17 +248,12 @@
oop lookup(int index, jchar* chars, int length, unsigned int hashValue);
- StringTable() : Hashtable<oop>((int)StringTableSize,
- sizeof (HashtableEntry<oop>)) {}
+ StringTable() : Hashtable<oop, mtSymbol>((int)StringTableSize,
+ sizeof (HashtableEntry<oop, mtSymbol>)) {}
- StringTable(HashtableBucket* t, int number_of_entries)
- : Hashtable<oop>((int)StringTableSize, sizeof (HashtableEntry<oop>), t,
+ StringTable(HashtableBucket<mtSymbol>* t, int number_of_entries)
+ : Hashtable<oop, mtSymbol>((int)StringTableSize, sizeof (HashtableEntry<oop, mtSymbol>), t,
number_of_entries) {}
-
- static bool use_alternate_hashcode() { return _seed != 0; }
- static jint seed() { return _seed; }
-
- unsigned int new_hash(oop s);
public:
// The string table
static StringTable* the_table() { return _the_table; }
@@ -276,10 +263,10 @@
_the_table = new StringTable();
}
- static void create_table(HashtableBucket* t, int length,
+ static void create_table(HashtableBucket<mtSymbol>* t, int length,
int number_of_entries) {
assert(_the_table == NULL, "One string table allowed.");
- assert((size_t)length == StringTableSize * sizeof(HashtableBucket),
+ assert((size_t)length == StringTableSize * sizeof(HashtableBucket<mtSymbol>),
"bad shared string size.");
_the_table = new StringTable(t, number_of_entries);
}
@@ -313,13 +300,13 @@
// Sharing
static void copy_buckets(char** top, char*end) {
- the_table()->Hashtable<oop>::copy_buckets(top, end);
+ the_table()->Hashtable<oop, mtSymbol>::copy_buckets(top, end);
}
static void copy_table(char** top, char*end) {
- the_table()->Hashtable<oop>::copy_table(top, end);
+ the_table()->Hashtable<oop, mtSymbol>::copy_table(top, end);
}
static void reverse() {
- the_table()->Hashtable<oop>::reverse();
+ the_table()->Hashtable<oop, mtSymbol>::reverse();
}
// Rehash the symbol table if it gets out of balance
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1168,9 +1168,9 @@
}
-void SystemDictionary::set_shared_dictionary(HashtableBucket* t, int length,
+void SystemDictionary::set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
int number_of_entries) {
- assert(length == _nof_buckets * sizeof(HashtableBucket),
+ assert(length == _nof_buckets * sizeof(HashtableBucket<mtClass>),
"bad shared dictionary size.");
_shared_dictionary = new Dictionary(_nof_buckets, t, number_of_entries);
}
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -32,6 +32,7 @@
#include "runtime/java.hpp"
#include "runtime/reflectionUtils.hpp"
#include "utilities/hashtable.hpp"
+#include "utilities/hashtable.inline.hpp"
// The system dictionary stores all loaded classes and maps:
//
@@ -72,7 +73,7 @@
class Dictionary;
class PlaceholderTable;
class LoaderConstraintTable;
-class HashtableBucket;
+template <MEMFLAGS F> class HashtableBucket;
class ResolutionErrorTable;
class SymbolPropertyTable;
@@ -363,7 +364,7 @@
static void copy_buckets(char** top, char* end);
static void copy_table(char** top, char* end);
static void reverse();
- static void set_shared_dictionary(HashtableBucket* t, int length,
+ static void set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
int number_of_entries);
// Printing
static void print() PRODUCT_RETURN;
--- a/hotspot/src/share/vm/code/codeBlob.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/code/codeBlob.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -144,7 +144,7 @@
// chunk of memory, its your job to free it.
if (p != NULL) {
// We need to allocate a chunk big enough to hold the OopMapSet and all of its OopMaps
- _oop_maps = (OopMapSet* )NEW_C_HEAP_ARRAY(unsigned char, p->heap_size());
+ _oop_maps = (OopMapSet* )NEW_C_HEAP_ARRAY(unsigned char, p->heap_size(), mtCode);
p->copy_to((address)_oop_maps);
} else {
_oop_maps = NULL;
@@ -180,7 +180,7 @@
void CodeBlob::flush() {
if (_oop_maps) {
- FREE_C_HEAP_ARRAY(unsigned char, _oop_maps);
+ FREE_C_HEAP_ARRAY(unsigned char, _oop_maps, mtCode);
_oop_maps = NULL;
}
_comments.free();
--- a/hotspot/src/share/vm/code/codeCache.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/code/codeCache.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -856,7 +856,7 @@
int bucketSize = 512;
int bucketLimit = maxCodeSize / bucketSize + 1;
- int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit);
+ int *buckets = NEW_C_HEAP_ARRAY(int, bucketLimit, mtCode);
memset(buckets,0,sizeof(int) * bucketLimit);
for (cb = first(); cb != NULL; cb = next(cb)) {
@@ -893,7 +893,7 @@
}
}
- FREE_C_HEAP_ARRAY(int, buckets);
+ FREE_C_HEAP_ARRAY(int, buckets, mtCode);
}
void CodeCache::print() {
--- a/hotspot/src/share/vm/code/codeCache.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/code/codeCache.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -88,6 +88,9 @@
// Lookup that does not fail if you lookup a zombie method (if you call this, be sure to know
// what you are doing)
static CodeBlob* find_blob_unsafe(void* start) {
+ // NMT can walk the stack before code cache is created
+ if (_heap == NULL) return NULL;
+
CodeBlob* result = (CodeBlob*)_heap->find_start(start);
// this assert is too strong because the heap code will return the
// heapblock containing start. That block can often be larger than
--- a/hotspot/src/share/vm/code/nmethod.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/code/nmethod.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -31,7 +31,7 @@
// This class is used internally by nmethods, to cache
// exception/pc/handler information.
-class ExceptionCache : public CHeapObj {
+class ExceptionCache : public CHeapObj<mtCode> {
friend class VMStructs;
private:
enum { cache_size = 16 };
--- a/hotspot/src/share/vm/code/stubs.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/code/stubs.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -101,7 +101,7 @@
// of the concrete stub (see also macro below). There's exactly
// one stub interface instance required per stub queue.
-class StubInterface: public CHeapObj {
+class StubInterface: public CHeapObj<mtCode> {
public:
// Initialization/finalization
virtual void initialize(Stub* self, int size) = 0; // called after creation (called twice if allocated via (request, commit))
@@ -152,7 +152,7 @@
// A StubQueue maintains a queue of stubs.
// Note: All sizes (spaces) are given in bytes.
-class StubQueue: public CHeapObj {
+class StubQueue: public CHeapObj<mtCode> {
friend class VMStructs;
private:
StubInterface* _stub_interface; // the interface prototype
--- a/hotspot/src/share/vm/compiler/abstractCompiler.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/compiler/abstractCompiler.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -29,7 +29,7 @@
typedef void (*initializer)(void);
-class AbstractCompiler : public CHeapObj {
+class AbstractCompiler : public CHeapObj<mtCompiler> {
private:
bool _is_initialized; // Mark whether compiler object is initialized
--- a/hotspot/src/share/vm/compiler/compileBroker.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -951,7 +951,7 @@
int compiler_count = c1_compiler_count + c2_compiler_count;
_method_threads =
- new (ResourceObj::C_HEAP) GrowableArray<CompilerThread*>(compiler_count, true);
+ new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<CompilerThread*>(compiler_count, true);
char name_buffer[256];
for (int i = 0; i < c2_compiler_count; i++) {
@@ -1627,7 +1627,7 @@
}
fp = fopen(fileBuf, "at");
if (fp != NULL) {
- file = NEW_C_HEAP_ARRAY(char, strlen(fileBuf)+1);
+ file = NEW_C_HEAP_ARRAY(char, strlen(fileBuf)+1, mtCompiler);
strcpy(file, fileBuf);
break;
}
@@ -1637,7 +1637,7 @@
} else {
if (LogCompilation && Verbose)
tty->print_cr("Opening compilation log %s", file);
- CompileLog* log = new(ResourceObj::C_HEAP) CompileLog(file, fp, thread_id);
+ CompileLog* log = new(ResourceObj::C_HEAP, mtCompiler) CompileLog(file, fp, thread_id);
thread->init_log(log);
if (xtty != NULL) {
--- a/hotspot/src/share/vm/compiler/compileBroker.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/compiler/compileBroker.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,7 +36,7 @@
//
// An entry in the compile queue. It represents a pending or current
// compilation.
-class CompileTask : public CHeapObj {
+class CompileTask : public CHeapObj<mtCompiler> {
friend class VMStructs;
private:
@@ -131,7 +131,7 @@
//
// Per Compiler Performance Counters.
//
-class CompilerCounters : public CHeapObj {
+class CompilerCounters : public CHeapObj<mtCompiler> {
public:
enum {
@@ -175,7 +175,7 @@
// CompileQueue
//
// A list of CompileTasks.
-class CompileQueue : public CHeapObj {
+class CompileQueue : public CHeapObj<mtCompiler> {
private:
const char* _name;
Monitor* _lock;
--- a/hotspot/src/share/vm/compiler/compileLog.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/compiler/compileLog.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -37,14 +37,14 @@
CompileLog::CompileLog(const char* file, FILE* fp, intx thread_id)
: _context(_context_buffer, sizeof(_context_buffer))
{
- initialize(new(ResourceObj::C_HEAP) fileStream(fp));
+ initialize(new(ResourceObj::C_HEAP, mtCompiler) fileStream(fp));
_file = file;
_file_end = 0;
_thread_id = thread_id;
_identities_limit = 0;
_identities_capacity = 400;
- _identities = NEW_C_HEAP_ARRAY(char, _identities_capacity);
+ _identities = NEW_C_HEAP_ARRAY(char, _identities_capacity, mtCompiler);
// link into the global list
{ MutexLocker locker(CompileTaskAlloc_lock);
@@ -56,7 +56,7 @@
CompileLog::~CompileLog() {
delete _out;
_out = NULL;
- FREE_C_HEAP_ARRAY(char, _identities);
+ FREE_C_HEAP_ARRAY(char, _identities, mtCompiler);
}
@@ -109,7 +109,7 @@
if (id >= _identities_capacity) {
int new_cap = _identities_capacity * 2;
if (new_cap <= id) new_cap = id + 100;
- _identities = REALLOC_C_HEAP_ARRAY(char, _identities, new_cap);
+ _identities = REALLOC_C_HEAP_ARRAY(char, _identities, new_cap, mtCompiler);
_identities_capacity = new_cap;
}
while (id >= _identities_limit) {
--- a/hotspot/src/share/vm/compiler/compilerOracle.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/compiler/compilerOracle.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/jniHandles.hpp"
-class MethodMatcher : public CHeapObj {
+class MethodMatcher : public CHeapObj<mtCompiler> {
public:
enum Mode {
Exact,
@@ -550,10 +550,12 @@
}
}
+static const char* default_cc_file = ".hotspot_compiler";
+
static const char* cc_file() {
#ifdef ASSERT
if (CompileCommandFile == NULL)
- return ".hotspot_compiler";
+ return default_cc_file;
#endif
return CompileCommandFile;
}
@@ -636,10 +638,17 @@
CompilerOracle::parse_from_string(CompileOnly, CompilerOracle::parse_compile_only);
if (CompilerOracle::has_command_file()) {
CompilerOracle::parse_from_file();
+ } else {
+ struct stat buf;
+ if (os::stat(default_cc_file, &buf) == 0) {
+ warning("%s file is present but has been ignored. "
+ "Run with -XX:CompileCommandFile=%s to load the file.",
+ default_cc_file, default_cc_file);
+ }
}
if (lists[PrintCommand] != NULL) {
if (PrintAssembly) {
- warning("CompileCommand and/or .hotspot_compiler file contains 'print' commands, but PrintAssembly is also enabled");
+ warning("CompileCommand and/or %s file contains 'print' commands, but PrintAssembly is also enabled", default_cc_file);
} else if (FLAG_IS_DEFAULT(DebugNonSafepoints)) {
warning("printing of assembly code is enabled; turning on DebugNonSafepoints to gain additional output");
DebugNonSafepoints = true;
--- a/hotspot/src/share/vm/compiler/oopMap.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/compiler/oopMap.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -599,7 +599,7 @@
#ifdef COMPILER2
-class DerivedPointerEntry : public CHeapObj {
+class DerivedPointerEntry : public CHeapObj<mtCompiler> {
private:
oop* _location; // Location of derived pointer (also pointing to the base)
intptr_t _offset; // Offset from base pointer
@@ -621,7 +621,7 @@
assert (!_active, "should not be active");
assert(_list == NULL || _list->length() == 0, "table not empty");
if (_list == NULL) {
- _list = new (ResourceObj::C_HEAP) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap
+ _list = new (ResourceObj::C_HEAP, mtCompiler) GrowableArray<DerivedPointerEntry*>(10, true); // Allocated on C heap
}
_active = true;
}
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -617,7 +617,7 @@
// A parallel-GC-thread-local allocation buffer for allocation into a
// CompactibleFreeListSpace.
-class CFLS_LAB : public CHeapObj {
+class CFLS_LAB : public CHeapObj<mtGC> {
// The space that this buffer allocates into.
CompactibleFreeListSpace* _cfls;
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -174,7 +174,7 @@
// This struct contains per-thread things necessary to support parallel
// young-gen collection.
-class CMSParGCThreadState: public CHeapObj {
+class CMSParGCThreadState: public CHeapObj<mtGC> {
public:
CFLS_LAB lab;
PromotionInfo promo;
@@ -229,7 +229,7 @@
if (CollectedHeap::use_parallel_gc_threads()) {
typedef CMSParGCThreadState* CMSParGCThreadStatePtr;
_par_gc_thread_states =
- NEW_C_HEAP_ARRAY(CMSParGCThreadStatePtr, ParallelGCThreads);
+ NEW_C_HEAP_ARRAY(CMSParGCThreadStatePtr, ParallelGCThreads, mtGC);
if (_par_gc_thread_states == NULL) {
vm_exit_during_initialization("Could not allocate par gc structs");
}
@@ -687,7 +687,7 @@
warning("task_queues allocation failure.");
return;
}
- _hash_seed = NEW_C_HEAP_ARRAY(int, num_queues);
+ _hash_seed = NEW_C_HEAP_ARRAY(int, num_queues, mtGC);
if (_hash_seed == NULL) {
warning("_hash_seed array allocation failure");
return;
@@ -737,7 +737,7 @@
assert(_young_gen != NULL, "no _young_gen");
_eden_chunk_index = 0;
_eden_chunk_capacity = (_young_gen->max_capacity()+CMSSamplingGrain)/CMSSamplingGrain;
- _eden_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, _eden_chunk_capacity);
+ _eden_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, _eden_chunk_capacity, mtGC);
if (_eden_chunk_array == NULL) {
_eden_chunk_capacity = 0;
warning("GC/CMS: _eden_chunk_array allocation failure");
@@ -750,35 +750,35 @@
const size_t max_plab_samples =
((DefNewGeneration*)_young_gen)->max_survivor_size()/MinTLABSize;
- _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads);
- _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples);
- _cursor = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads);
+ _survivor_plab_array = NEW_C_HEAP_ARRAY(ChunkArray, ParallelGCThreads, mtGC);
+ _survivor_chunk_array = NEW_C_HEAP_ARRAY(HeapWord*, 2*max_plab_samples, mtGC);
+ _cursor = NEW_C_HEAP_ARRAY(size_t, ParallelGCThreads, mtGC);
if (_survivor_plab_array == NULL || _survivor_chunk_array == NULL
|| _cursor == NULL) {
warning("Failed to allocate survivor plab/chunk array");
if (_survivor_plab_array != NULL) {
- FREE_C_HEAP_ARRAY(ChunkArray, _survivor_plab_array);
+ FREE_C_HEAP_ARRAY(ChunkArray, _survivor_plab_array, mtGC);
_survivor_plab_array = NULL;
}
if (_survivor_chunk_array != NULL) {
- FREE_C_HEAP_ARRAY(HeapWord*, _survivor_chunk_array);
+ FREE_C_HEAP_ARRAY(HeapWord*, _survivor_chunk_array, mtGC);
_survivor_chunk_array = NULL;
}
if (_cursor != NULL) {
- FREE_C_HEAP_ARRAY(size_t, _cursor);
+ FREE_C_HEAP_ARRAY(size_t, _cursor, mtGC);
_cursor = NULL;
}
} else {
_survivor_chunk_capacity = 2*max_plab_samples;
for (uint i = 0; i < ParallelGCThreads; i++) {
- HeapWord** vec = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples);
+ HeapWord** vec = NEW_C_HEAP_ARRAY(HeapWord*, max_plab_samples, mtGC);
if (vec == NULL) {
warning("Failed to allocate survivor plab array");
for (int j = i; j > 0; j--) {
- FREE_C_HEAP_ARRAY(HeapWord*, _survivor_plab_array[j-1].array());
+ FREE_C_HEAP_ARRAY(HeapWord*, _survivor_plab_array[j-1].array(), mtGC);
}
- FREE_C_HEAP_ARRAY(ChunkArray, _survivor_plab_array);
- FREE_C_HEAP_ARRAY(HeapWord*, _survivor_chunk_array);
+ FREE_C_HEAP_ARRAY(ChunkArray, _survivor_plab_array, mtGC);
+ FREE_C_HEAP_ARRAY(HeapWord*, _survivor_chunk_array, mtGC);
_survivor_plab_array = NULL;
_survivor_chunk_array = NULL;
_survivor_chunk_capacity = 0;
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -161,7 +161,7 @@
// Represents a marking stack used by the CMS collector.
// Ideally this should be GrowableArray<> just like MSC's marking stack(s).
-class CMSMarkStack: public CHeapObj {
+class CMSMarkStack: public CHeapObj<mtGC> {
//
friend class CMSCollector; // to get at expasion stats further below
//
@@ -265,7 +265,7 @@
// Survivor Chunk Array in support of parallelization of
// Survivor Space rescan.
-class ChunkArray: public CHeapObj {
+class ChunkArray: public CHeapObj<mtGC> {
size_t _index;
size_t _capacity;
size_t _overflows;
@@ -506,7 +506,7 @@
};
-class CMSCollector: public CHeapObj {
+class CMSCollector: public CHeapObj<mtGC> {
friend class VMStructs;
friend class ConcurrentMarkSweepThread;
friend class ConcurrentMarkSweepGeneration;
@@ -553,8 +553,8 @@
// The following array-pair keeps track of mark words
// displaced for accomodating overflow list above.
// This code will likely be revisited under RFE#4922830.
- Stack<oop> _preserved_oop_stack;
- Stack<markOop> _preserved_mark_stack;
+ Stack<oop, mtGC> _preserved_oop_stack;
+ Stack<markOop, mtGC> _preserved_mark_stack;
int* _hash_seed;
--- a/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/collectionSetChooser.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -28,7 +28,7 @@
#include "gc_implementation/g1/heapRegion.hpp"
#include "utilities/growableArray.hpp"
-class CollectionSetChooser: public CHeapObj {
+class CollectionSetChooser: public CHeapObj<mtGC> {
GrowableArray<HeapRegion*> _regions;
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -79,7 +79,7 @@
_n_threads = _n_worker_threads + 1;
reset_threshold_step();
- _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads);
+ _threads = NEW_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _n_threads, mtGC);
int worker_id_offset = (int)DirtyCardQueueSet::num_par_ids();
ConcurrentG1RefineThread *next = NULL;
for (int i = _n_threads - 1; i >= 0; i--) {
@@ -157,7 +157,7 @@
_def_use_cache = true;
_use_cache = true;
_hot_cache_size = (1 << G1ConcRSLogCacheSize);
- _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size);
+ _hot_cache = NEW_C_HEAP_ARRAY(jbyte*, _hot_cache_size, mtGC);
_n_hot = 0;
_hot_cache_idx = 0;
@@ -191,18 +191,18 @@
// Please see the comment in allocate_card_count_cache
// for why we call os::malloc() and os::free() directly.
assert(_card_counts != NULL, "Logic");
- os::free(_card_counts);
+ os::free(_card_counts, mtGC);
assert(_card_epochs != NULL, "Logic");
- os::free(_card_epochs);
+ os::free(_card_epochs, mtGC);
assert(_hot_cache != NULL, "Logic");
- FREE_C_HEAP_ARRAY(jbyte*, _hot_cache);
+ FREE_C_HEAP_ARRAY(jbyte*, _hot_cache, mtGC);
}
if (_threads != NULL) {
for (int i = 0; i < _n_threads; i++) {
delete _threads[i];
}
- FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads);
+ FREE_C_HEAP_ARRAY(ConcurrentG1RefineThread*, _threads, mtGC);
}
}
@@ -436,17 +436,17 @@
size_t counts_size = n * sizeof(CardCountCacheEntry);
size_t epochs_size = n * sizeof(CardEpochCacheEntry);
- *counts = (CardCountCacheEntry*) os::malloc(counts_size);
+ *counts = (CardCountCacheEntry*) os::malloc(counts_size, mtGC);
if (*counts == NULL) {
// allocation was unsuccessful
return false;
}
- *epochs = (CardEpochCacheEntry*) os::malloc(epochs_size);
+ *epochs = (CardEpochCacheEntry*) os::malloc(epochs_size, mtGC);
if (*epochs == NULL) {
// allocation was unsuccessful - free counts array
assert(*counts != NULL, "must be");
- os::free(*counts);
+ os::free(*counts, mtGC);
*counts = NULL;
return false;
}
@@ -479,8 +479,8 @@
// Allocation was successful.
// We can just free the old arrays; we're
// not interested in preserving the contents
- if (_card_counts != NULL) os::free(_card_counts);
- if (_card_epochs != NULL) os::free(_card_epochs);
+ if (_card_counts != NULL) os::free(_card_counts, mtGC);
+ if (_card_epochs != NULL) os::free(_card_epochs, mtGC);
// Cache the size of the arrays and the index that got us there.
_n_card_counts = cache_size;
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
class ConcurrentG1RefineThread;
class G1RemSet;
-class ConcurrentG1Refine: public CHeapObj {
+class ConcurrentG1Refine: public CHeapObj<mtGC> {
ConcurrentG1RefineThread** _threads;
int _n_threads;
int _n_worker_threads;
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -42,6 +42,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
+#include "services/memTracker.hpp"
// Concurrent marking bit map wrapper
@@ -53,6 +54,8 @@
ReservedSpace brs(ReservedSpace::allocation_align_size_up(
(_bmWordSize >> (_shifter + LogBitsPerByte)) + 1));
+ MemTracker::record_virtual_memory_type((address)brs.base(), mtGC);
+
guarantee(brs.is_reserved(), "couldn't allocate concurrent marking bit map");
// For now we'll just commit all of the bit map up fromt.
// Later on we'll try to be more parsimonious with swap.
@@ -161,7 +164,7 @@
{}
void CMMarkStack::allocate(size_t size) {
- _base = NEW_C_HEAP_ARRAY(oop, size);
+ _base = NEW_C_HEAP_ARRAY(oop, size, mtGC);
if (_base == NULL) {
vm_exit_during_initialization("Failed to allocate CM region mark stack");
}
@@ -173,7 +176,7 @@
CMMarkStack::~CMMarkStack() {
if (_base != NULL) {
- FREE_C_HEAP_ARRAY(oop, _base);
+ FREE_C_HEAP_ARRAY(oop, _base, mtGC);
}
}
@@ -480,11 +483,11 @@
_root_regions.init(_g1h, this);
- _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num);
- _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num);
-
- _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_task_num);
- _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_task_num);
+ _tasks = NEW_C_HEAP_ARRAY(CMTask*, _max_task_num, mtGC);
+ _accum_task_vtime = NEW_C_HEAP_ARRAY(double, _max_task_num, mtGC);
+
+ _count_card_bitmaps = NEW_C_HEAP_ARRAY(BitMap, _max_task_num, mtGC);
+ _count_marked_bytes = NEW_C_HEAP_ARRAY(size_t*, _max_task_num, mtGC);
BitMap::idx_t card_bm_size = _card_bm.size();
@@ -496,7 +499,7 @@
_task_queues->register_queue(i, task_queue);
_count_card_bitmaps[i] = BitMap(card_bm_size, false);
- _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, (size_t) max_regions);
+ _count_marked_bytes[i] = NEW_C_HEAP_ARRAY(size_t, (size_t) max_regions, mtGC);
_tasks[i] = new CMTask(i, this,
_count_marked_bytes[i],
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -30,8 +30,8 @@
class G1CollectedHeap;
class CMTask;
-typedef GenericTaskQueue<oop> CMTaskQueue;
-typedef GenericTaskQueueSet<CMTaskQueue> CMTaskQueueSet;
+typedef GenericTaskQueue<oop, mtGC> CMTaskQueue;
+typedef GenericTaskQueueSet<CMTaskQueue, mtGC> CMTaskQueueSet;
// Closure used by CM during concurrent reference discovery
// and reference processing (during remarking) to determine
@@ -343,7 +343,7 @@
class ConcurrentMarkThread;
-class ConcurrentMark : public CHeapObj {
+class ConcurrentMark: public CHeapObj<mtGC> {
friend class ConcurrentMarkThread;
friend class CMTask;
friend class CMBitMapClosure;
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -32,7 +32,7 @@
// A closure class for processing card table entries. Note that we don't
// require these closure objects to be stack-allocated.
-class CardTableEntryClosure: public CHeapObj {
+class CardTableEntryClosure: public CHeapObj<mtGC> {
public:
// Process the card whose card table entry is "card_ptr". If returns
// "false", terminate the iteration early.
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -27,6 +27,7 @@
#include "memory/space.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/java.hpp"
+#include "services/memTracker.hpp"
//////////////////////////////////////////////////////////////////////
// G1BlockOffsetSharedArray
@@ -44,6 +45,9 @@
if (!_vs.initialize(rs, 0)) {
vm_exit_during_initialization("Could not reserve enough space for heap offset array");
}
+
+ MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
+
_offset_array = (u_char*)_vs.low_boundary();
resize(init_word_size);
if (TraceBlockOffsetTable) {
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -117,7 +117,7 @@
// Here is the shared array type.
-class G1BlockOffsetSharedArray: public CHeapObj {
+class G1BlockOffsetSharedArray: public CHeapObj<mtGC> {
friend class G1BlockOffsetArray;
friend class G1BlockOffsetArrayContigSpace;
friend class VMStructs;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1916,14 +1916,14 @@
assert(n_rem_sets > 0, "Invariant.");
HeapRegionRemSetIterator** iter_arr =
- NEW_C_HEAP_ARRAY(HeapRegionRemSetIterator*, n_queues);
+ NEW_C_HEAP_ARRAY(HeapRegionRemSetIterator*, n_queues, mtGC);
for (int i = 0; i < n_queues; i++) {
iter_arr[i] = new HeapRegionRemSetIterator();
}
_rem_set_iterator = iter_arr;
- _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues);
- _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues);
+ _worker_cset_start_region = NEW_C_HEAP_ARRAY(HeapRegion*, n_queues, mtGC);
+ _worker_cset_start_region_time_stamp = NEW_C_HEAP_ARRAY(unsigned int, n_queues, mtGC);
for (int i = 0; i < n_queues; i++) {
RefToScanQueue* q = new RefToScanQueue();
@@ -2082,7 +2082,7 @@
_in_cset_fast_test_length = max_regions();
_in_cset_fast_test_base =
- NEW_C_HEAP_ARRAY(bool, (size_t) _in_cset_fast_test_length);
+ NEW_C_HEAP_ARRAY(bool, (size_t) _in_cset_fast_test_length, mtGC);
// We're biasing _in_cset_fast_test to avoid subtracting the
// beginning of the heap every time we want to index; basically
@@ -3505,7 +3505,7 @@
G1CollectedHeap::setup_surviving_young_words() {
assert(_surviving_young_words == NULL, "pre-condition");
uint array_length = g1_policy()->young_cset_region_length();
- _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, (size_t) array_length);
+ _surviving_young_words = NEW_C_HEAP_ARRAY(size_t, (size_t) array_length, mtGC);
if (_surviving_young_words == NULL) {
vm_exit_out_of_memory(sizeof(size_t) * array_length,
"Not enough space for young surv words summary.");
@@ -3530,7 +3530,7 @@
void
G1CollectedHeap::cleanup_surviving_young_words() {
guarantee( _surviving_young_words != NULL, "pre-condition" );
- FREE_C_HEAP_ARRAY(size_t, _surviving_young_words);
+ FREE_C_HEAP_ARRAY(size_t, _surviving_young_words, mtGC);
_surviving_young_words = NULL;
}
@@ -4073,7 +4073,7 @@
void G1CollectedHeap::init_for_evac_failure(OopsInHeapRegionClosure* cl) {
_drain_in_progress = false;
set_evac_failure_closure(cl);
- _evac_failure_scan_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(40, true);
+ _evac_failure_scan_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(40, true);
}
void G1CollectedHeap::finalize_for_evac_failure() {
@@ -4207,9 +4207,9 @@
if (_objs_with_preserved_marks == NULL) {
assert(_preserved_marks_of_objs == NULL, "Both or none.");
_objs_with_preserved_marks =
- new (ResourceObj::C_HEAP) GrowableArray<oop>(40, true);
+ new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(40, true);
_preserved_marks_of_objs =
- new (ResourceObj::C_HEAP) GrowableArray<markOop>(40, true);
+ new (ResourceObj::C_HEAP, mtGC) GrowableArray<markOop>(40, true);
}
_objs_with_preserved_marks->push(obj);
_preserved_marks_of_objs->push(m);
@@ -4269,7 +4269,7 @@
uint array_length = PADDING_ELEM_NUM +
real_length +
PADDING_ELEM_NUM;
- _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length);
+ _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
if (_surviving_young_words_base == NULL)
vm_exit_out_of_memory(array_length * sizeof(size_t),
"Not enough space for young surv histo.");
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -62,8 +62,8 @@
class ConcurrentG1Refine;
class GenerationCounters;
-typedef OverflowTaskQueue<StarTask> RefToScanQueue;
-typedef GenericTaskQueueSet<RefToScanQueue> RefToScanQueueSet;
+typedef OverflowTaskQueue<StarTask, mtGC> RefToScanQueue;
+typedef GenericTaskQueueSet<RefToScanQueue, mtGC> RefToScanQueueSet;
typedef int RegionIdx_t; // needs to hold [ 0..max_regions() )
typedef int CardIdx_t; // needs to hold [ 0..CardsPerRegion )
@@ -74,7 +74,7 @@
GCAllocPurposeCount
};
-class YoungList : public CHeapObj {
+class YoungList : public CHeapObj<mtGC> {
private:
G1CollectedHeap* _g1h;
@@ -1772,7 +1772,7 @@
G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num);
~G1ParScanThreadState() {
- FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base);
+ FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC);
}
RefToScanQueue* refs() { return _refs; }
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
// TraceGen0Time collects data on _both_ young and mixed evacuation pauses
// (the latter may contain non-young regions - i.e. regions that are
// technically in Gen1) while TraceGen1Time collects data about full GCs.
-class TraceGen0TimeData : public CHeapObj {
+class TraceGen0TimeData : public CHeapObj<mtGC> {
private:
unsigned _young_pause_num;
unsigned _mixed_pause_num;
@@ -86,7 +86,7 @@
void print() const;
};
-class TraceGen1TimeData : public CHeapObj {
+class TraceGen1TimeData : public CHeapObj<mtGC> {
private:
NumberSeq _all_full_gc_times;
@@ -131,7 +131,7 @@
//
// NewSize and MaxNewSize override NewRatio. So, NewRatio is ignored if it is
// combined with either NewSize or MaxNewSize. (A warning message is printed.)
-class G1YoungGenSizer : public CHeapObj {
+class G1YoungGenSizer : public CHeapObj<mtGC> {
private:
enum SizerKind {
SizerDefaults,
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MMUTracker.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
/***** ALL TIMES ARE IN SECS!!!!!!! *****/
// this is the "interface"
-class G1MMUTracker: public CHeapObj {
+class G1MMUTracker: public CHeapObj<mtGC> {
protected:
double _time_slice;
double _max_gc_time; // this is per time slice
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MonitoringSupport.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -112,7 +112,7 @@
// do which is important as we want to keep the eden region allocation
// path as low-overhead as possible.
-class G1MonitoringSupport : public CHeapObj {
+class G1MonitoringSupport : public CHeapObj<mtGC> {
friend class VMStructs;
G1CollectedHeap* _g1h;
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -75,7 +75,7 @@
{
_seq_task = new SubTasksDone(NumSeqTasks);
guarantee(n_workers() > 0, "There should be some workers");
- _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers());
+ _cset_rs_update_cl = NEW_C_HEAP_ARRAY(OopsInHeapRegionClosure*, n_workers(), mtGC);
for (uint i = 0; i < n_workers(); i++) {
_cset_rs_update_cl[i] = NULL;
}
@@ -86,7 +86,7 @@
for (uint i = 0; i < n_workers(); i++) {
assert(_cset_rs_update_cl[i] == NULL, "it should be");
}
- FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl);
+ FREE_C_HEAP_ARRAY(OopsInHeapRegionClosure*, _cset_rs_update_cl, mtGC);
}
void CountNonCleanMemRegionClosure::do_MemRegion(MemRegion mr) {
@@ -416,7 +416,7 @@
// _seq_task->set_n_termination((int)n_workers());
}
guarantee( _cards_scanned == NULL, "invariant" );
- _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers());
+ _cards_scanned = NEW_C_HEAP_ARRAY(size_t, n_workers(), mtGC);
for (uint i = 0; i < n_workers(); ++i) {
_cards_scanned[i] = 0;
}
@@ -487,7 +487,7 @@
for (uint i = 0; i < n_workers(); ++i) {
_total_cards_scanned += _cards_scanned[i];
}
- FREE_C_HEAP_ARRAY(size_t, _cards_scanned);
+ FREE_C_HEAP_ARRAY(size_t, _cards_scanned, mtGC);
_cards_scanned = NULL;
// Cleanup after copy
_g1->set_refine_cte_cl_concurrency(true);
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,7 +36,7 @@
// external heap references into it. Uses a mod ref bs to track updates,
// so that they can be used to update the individual region remsets.
-class G1RemSet: public CHeapObj {
+class G1RemSet: public CHeapObj<mtGC> {
protected:
G1CollectedHeap* _g1;
unsigned _conc_refine_cards;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,7 +36,7 @@
// OtherRegionsTable
-class PerRegionTable: public CHeapObj {
+class PerRegionTable: public CHeapObj<mtGC> {
friend class OtherRegionsTable;
friend class HeapRegionRemSetIterator;
@@ -272,9 +272,9 @@
_from_card_cache_max_regions = max_regions;
int n_par_rs = HeapRegionRemSet::num_par_rem_sets();
- _from_card_cache = NEW_C_HEAP_ARRAY(int*, n_par_rs);
+ _from_card_cache = NEW_C_HEAP_ARRAY(int*, n_par_rs, mtGC);
for (int i = 0; i < n_par_rs; i++) {
- _from_card_cache[i] = NEW_C_HEAP_ARRAY(int, max_regions);
+ _from_card_cache[i] = NEW_C_HEAP_ARRAY(int, max_regions, mtGC);
for (size_t j = 0; j < max_regions; j++) {
_from_card_cache[i][j] = -1; // An invalid value.
}
@@ -977,9 +977,9 @@
&& _recorded_cards == NULL
&& _recorded_regions == NULL,
"Inv");
- _recorded_oops = NEW_C_HEAP_ARRAY(OopOrNarrowOopStar, MaxRecorded);
- _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded);
- _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded);
+ _recorded_oops = NEW_C_HEAP_ARRAY(OopOrNarrowOopStar, MaxRecorded, mtGC);
+ _recorded_cards = NEW_C_HEAP_ARRAY(HeapWord*, MaxRecorded, mtGC);
+ _recorded_regions = NEW_C_HEAP_ARRAY(HeapRegion*, MaxRecorded, mtGC);
}
if (_n_recorded == MaxRecorded) {
gclog_or_tty->print_cr("Filled up 'recorded' (%d).", MaxRecorded);
@@ -1000,8 +1000,8 @@
assert(_n_recorded_events == 0
&& _recorded_event_index == NULL,
"Inv");
- _recorded_events = NEW_C_HEAP_ARRAY(Event, MaxRecordedEvents);
- _recorded_event_index = NEW_C_HEAP_ARRAY(int, MaxRecordedEvents);
+ _recorded_events = NEW_C_HEAP_ARRAY(Event, MaxRecordedEvents, mtGC);
+ _recorded_event_index = NEW_C_HEAP_ARRAY(int, MaxRecordedEvents, mtGC);
}
if (_n_recorded_events == MaxRecordedEvents) {
gclog_or_tty->print_cr("Filled up 'recorded_events' (%d).", MaxRecordedEvents);
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -165,7 +165,7 @@
static void print_from_card_cache();
};
-class HeapRegionRemSet : public CHeapObj {
+class HeapRegionRemSet : public CHeapObj<mtGC> {
friend class VMStructs;
friend class HeapRegionRemSetIterator;
@@ -332,7 +332,7 @@
#endif
};
-class HeapRegionRemSetIterator : public CHeapObj {
+class HeapRegionRemSetIterator : public CHeapObj<mtGC> {
// The region over which we're iterating.
const HeapRegionRemSet* _hrrs;
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -86,7 +86,7 @@
_allocated_length = 0;
_max_length = max_length;
- _regions = NEW_C_HEAP_ARRAY(HeapRegion*, max_length);
+ _regions = NEW_C_HEAP_ARRAY(HeapRegion*, max_length, mtGC);
memset(_regions, 0, (size_t) max_length * sizeof(HeapRegion*));
_regions_biased = _regions - ((uintx) bottom >> _region_shift);
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -53,7 +53,7 @@
//
// and maintain that: _length <= _allocated_length <= _max_length
-class HeapRegionSeq: public CHeapObj {
+class HeapRegionSeq: public CHeapObj<mtGC> {
friend class VMStructs;
// The array that holds the HeapRegions.
--- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -126,7 +126,7 @@
return res;
} else {
// Allocate space for the BufferNode in front of the buffer.
- char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size());
+ char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size(), mtGC);
return BufferNode::make_buffer_from_block(b);
}
}
@@ -149,7 +149,7 @@
assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong.");
void* b = BufferNode::make_block_from_node(_buf_free_list);
_buf_free_list = _buf_free_list->next();
- FREE_C_HEAP_ARRAY(char, b);
+ FREE_C_HEAP_ARRAY(char, b, mtGC);
_buf_free_list_sz --;
n--;
}
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -208,7 +208,7 @@
PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold, -1);
_shared_satb_queue.set_lock(lock);
if (ParallelGCThreads > 0) {
- _par_closures = NEW_C_HEAP_ARRAY(ObjectClosure*, ParallelGCThreads);
+ _par_closures = NEW_C_HEAP_ARRAY(ObjectClosure*, ParallelGCThreads, mtGC);
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -148,8 +148,8 @@
RSHashTable::RSHashTable(size_t capacity) :
_capacity(capacity), _capacity_mask(capacity-1),
_occupied_entries(0), _occupied_cards(0),
- _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity)),
- _buckets(NEW_C_HEAP_ARRAY(int, capacity)),
+ _entries((SparsePRTEntry*)NEW_C_HEAP_ARRAY(char, SparsePRTEntry::size() * capacity, mtGC)),
+ _buckets(NEW_C_HEAP_ARRAY(int, capacity, mtGC)),
_free_list(NullEntry), _free_region(0)
{
clear();
@@ -157,11 +157,11 @@
RSHashTable::~RSHashTable() {
if (_entries != NULL) {
- FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries);
+ FREE_C_HEAP_ARRAY(SparsePRTEntry, _entries, mtGC);
_entries = NULL;
}
if (_buckets != NULL) {
- FREE_C_HEAP_ARRAY(int, _buckets);
+ FREE_C_HEAP_ARRAY(int, _buckets, mtGC);
_buckets = NULL;
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -42,7 +42,7 @@
// insertions only enqueue old versions for deletions, but do not delete
// old versions synchronously.
-class SparsePRTEntry: public CHeapObj {
+class SparsePRTEntry: public CHeapObj<mtGC> {
public:
enum SomePublicConstants {
NullEntry = -1,
@@ -101,7 +101,7 @@
};
-class RSHashTable : public CHeapObj {
+class RSHashTable : public CHeapObj<mtGC> {
friend class RSHashTableIter;
--- a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -43,7 +43,7 @@
reset();
if (summary_surv_rates_len > 0) {
size_t length = summary_surv_rates_len;
- _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length);
+ _summary_surv_rates = NEW_C_HEAP_ARRAY(NumberSeq*, length, mtGC);
for (size_t i = 0; i < length; ++i) {
_summary_surv_rates[i] = new NumberSeq();
}
@@ -90,9 +90,9 @@
double* old_accum_surv_rate_pred = _accum_surv_rate_pred;
TruncatedSeq** old_surv_rate_pred = _surv_rate_pred;
- _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num);
- _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num);
- _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num);
+ _surv_rate = NEW_C_HEAP_ARRAY(double, _region_num, mtGC);
+ _accum_surv_rate_pred = NEW_C_HEAP_ARRAY(double, _region_num, mtGC);
+ _surv_rate_pred = NEW_C_HEAP_ARRAY(TruncatedSeq*, _region_num, mtGC);
for (size_t i = 0; i < _stats_arrays_length; ++i) {
_surv_rate_pred[i] = old_surv_rate_pred[i];
@@ -104,13 +104,13 @@
_stats_arrays_length = _region_num;
if (old_surv_rate != NULL) {
- FREE_C_HEAP_ARRAY(double, old_surv_rate);
+ FREE_C_HEAP_ARRAY(double, old_surv_rate, mtGC);
}
if (old_accum_surv_rate_pred != NULL) {
- FREE_C_HEAP_ARRAY(double, old_accum_surv_rate_pred);
+ FREE_C_HEAP_ARRAY(double, old_accum_surv_rate_pred, mtGC);
}
if (old_surv_rate_pred != NULL) {
- FREE_C_HEAP_ARRAY(TruncatedSeq*, old_surv_rate_pred);
+ FREE_C_HEAP_ARRAY(TruncatedSeq*, old_surv_rate_pred, mtGC);
}
}
--- a/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/g1/survRateGroup.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -29,7 +29,7 @@
class G1CollectorPolicy;
-class SurvRateGroup : public CHeapObj {
+class SurvRateGroup : public CHeapObj<mtGC> {
private:
G1CollectorPolicy* _g1p;
const char* _name;
--- a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -457,12 +457,12 @@
if (_lowest_non_clean[i] != NULL) {
assert(n_chunks != _lowest_non_clean_chunk_size[i],
"logical consequence");
- FREE_C_HEAP_ARRAY(CardPtr, _lowest_non_clean[i]);
+ FREE_C_HEAP_ARRAY(CardPtr, _lowest_non_clean[i], mtGC);
_lowest_non_clean[i] = NULL;
}
// Now allocate a new one if necessary.
if (_lowest_non_clean[i] == NULL) {
- _lowest_non_clean[i] = NEW_C_HEAP_ARRAY(CardPtr, n_chunks);
+ _lowest_non_clean[i] = NEW_C_HEAP_ARRAY(CardPtr, n_chunks, mtGC);
_lowest_non_clean_chunk_size[i] = n_chunks;
_lowest_non_clean_base_chunk_index[i] = addr_to_chunk_index(covered.start());
for (int j = 0; j < (int)n_chunks; j++)
--- a/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parGCAllocBuffer.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
class PLABStats;
// A per-thread allocation buffer used during GC.
-class ParGCAllocBuffer: public CHeapObj {
+class ParGCAllocBuffer: public CHeapObj<mtGC> {
protected:
char head[32];
size_t _word_sz; // in HeapWord units
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -59,7 +59,7 @@
Generation* old_gen_,
int thread_num_,
ObjToScanQueueSet* work_queue_set_,
- Stack<oop>* overflow_stacks_,
+ Stack<oop, mtGC>* overflow_stacks_,
size_t desired_plab_sz_,
ParallelTaskTerminator& term_) :
_to_space(to_space_), _old_gen(old_gen_), _young_gen(gen_), _thread_num(thread_num_),
@@ -184,7 +184,7 @@
assert(ParGCUseLocalOverflow, "Else should not call");
assert(young_gen()->overflow_list() == NULL, "Error");
ObjToScanQueue* queue = work_queue();
- Stack<oop>* const of_stack = overflow_stack();
+ Stack<oop, mtGC>* const of_stack = overflow_stack();
const size_t num_overflow_elems = of_stack->size();
const size_t space_available = queue->max_elems() - queue->size();
const size_t num_take_elems = MIN3(space_available / 4,
@@ -297,7 +297,7 @@
ParNewGeneration& gen,
Generation& old_gen,
ObjToScanQueueSet& queue_set,
- Stack<oop>* overflow_stacks_,
+ Stack<oop, mtGC>* overflow_stacks_,
size_t desired_plab_sz,
ParallelTaskTerminator& term);
@@ -331,7 +331,7 @@
ParScanThreadStateSet::ParScanThreadStateSet(
int num_threads, Space& to_space, ParNewGeneration& gen,
Generation& old_gen, ObjToScanQueueSet& queue_set,
- Stack<oop>* overflow_stacks,
+ Stack<oop, mtGC>* overflow_stacks,
size_t desired_plab_sz, ParallelTaskTerminator& term)
: ResourceArray(sizeof(ParScanThreadState), num_threads),
_gen(gen), _next_gen(old_gen), _term(term)
@@ -649,9 +649,14 @@
_overflow_stacks = NULL;
if (ParGCUseLocalOverflow) {
- _overflow_stacks = NEW_C_HEAP_ARRAY(Stack<oop>, ParallelGCThreads);
+
+ // typedef to workaround NEW_C_HEAP_ARRAY macro, which can not deal
+ // with ','
+ typedef Stack<oop, mtGC> GCOopStack;
+
+ _overflow_stacks = NEW_C_HEAP_ARRAY(GCOopStack, ParallelGCThreads, mtGC);
for (size_t i = 0; i < ParallelGCThreads; ++i) {
- new (_overflow_stacks + i) Stack<oop>();
+ new (_overflow_stacks + i) Stack<oop, mtGC>();
}
}
@@ -1401,7 +1406,7 @@
assert(_num_par_pushes > 0, "Tautology");
#endif
if (from_space_obj->forwardee() == from_space_obj) {
- oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1);
+ oopDesc* listhead = NEW_C_HEAP_ARRAY(oopDesc, 1, mtGC);
listhead->forward_to(from_space_obj);
from_space_obj = listhead;
}
@@ -1553,7 +1558,7 @@
// This can become a scaling bottleneck when there is work queue overflow coincident
// with promotion failure.
oopDesc* f = cur;
- FREE_C_HEAP_ARRAY(oopDesc, f);
+ FREE_C_HEAP_ARRAY(oopDesc, f, mtGC);
} else if (par_scan_state->should_be_partially_scanned(obj_to_push, cur)) {
assert(arrayOop(cur)->length() == 0, "entire array remaining to be scanned");
obj_to_push = cur;
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -41,7 +41,7 @@
// in genOopClosures.inline.hpp.
typedef Padded<OopTaskQueue> ObjToScanQueue;
-typedef GenericTaskQueueSet<ObjToScanQueue> ObjToScanQueueSet;
+typedef GenericTaskQueueSet<ObjToScanQueue, mtGC> ObjToScanQueueSet;
class ParKeepAliveClosure: public DefNewGeneration::KeepAliveClosure {
private:
@@ -59,7 +59,7 @@
friend class ParScanThreadStateSet;
private:
ObjToScanQueue *_work_queue;
- Stack<oop>* const _overflow_stack;
+ Stack<oop, mtGC>* const _overflow_stack;
ParGCAllocBuffer _to_space_alloc_buffer;
@@ -127,7 +127,7 @@
ParScanThreadState(Space* to_space_, ParNewGeneration* gen_,
Generation* old_gen_, int thread_num_,
ObjToScanQueueSet* work_queue_set_,
- Stack<oop>* overflow_stacks_,
+ Stack<oop, mtGC>* overflow_stacks_,
size_t desired_plab_sz_,
ParallelTaskTerminator& term_);
@@ -151,7 +151,7 @@
void trim_queues(int max_size);
// Private overflow stack usage
- Stack<oop>* overflow_stack() { return _overflow_stack; }
+ Stack<oop, mtGC>* overflow_stack() { return _overflow_stack; }
bool take_from_overflow_stack();
void push_on_overflow_stack(oop p);
@@ -312,7 +312,7 @@
ObjToScanQueueSet* _task_queues;
// Per-worker-thread local overflow stacks
- Stack<oop>* _overflow_stacks;
+ Stack<oop, mtGC>* _overflow_stacks;
// Desired size of survivor space plab's
PLABStats _plab_stats;
--- a/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parOopClosures.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -32,7 +32,7 @@
class ParScanThreadState;
class ParNewGeneration;
typedef Padded<OopTaskQueue> ObjToScanQueue;
-typedef GenericTaskQueueSet<ObjToScanQueue> ObjToScanQueueSet;
+typedef GenericTaskQueueSet<ObjToScanQueue, mtGC> ObjToScanQueueSet;
class ParallelTaskTerminator;
class ParScanClosure: public OopsInGenClosure {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/adjoiningGenerations.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
// must be shrunk. Adjusting the boundary between the generations
// is called for in this class.
-class AdjoiningGenerations : public CHeapObj {
+class AdjoiningGenerations : public CHeapObj<mtGC> {
friend class VMStructs;
private:
// The young generation and old generation, respectively
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -116,7 +116,7 @@
}
GCTaskQueue* GCTaskQueue::create_on_c_heap() {
- GCTaskQueue* result = new(ResourceObj::C_HEAP) GCTaskQueue(true);
+ GCTaskQueue* result = new(ResourceObj::C_HEAP, mtGC) GCTaskQueue(true);
if (TraceGCTaskQueue) {
tty->print_cr("GCTaskQueue::create_on_c_heap()"
" returns " INTPTR_FORMAT,
@@ -403,19 +403,19 @@
_queue = SynchronizedGCTaskQueue::create(unsynchronized_queue, lock());
_noop_task = NoopGCTask::create_on_c_heap();
_idle_inactive_task = WaitForBarrierGCTask::create_on_c_heap();
- _resource_flag = NEW_C_HEAP_ARRAY(bool, workers());
+ _resource_flag = NEW_C_HEAP_ARRAY(bool, workers(), mtGC);
{
// Set up worker threads.
// Distribute the workers among the available processors,
// unless we were told not to, or if the os doesn't want to.
- uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers());
+ uint* processor_assignment = NEW_C_HEAP_ARRAY(uint, workers(), mtGC);
if (!BindGCTaskThreadsToCPUs ||
!os::distribute_processes(workers(), processor_assignment)) {
for (uint a = 0; a < workers(); a += 1) {
processor_assignment[a] = sentinel_worker();
}
}
- _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers());
+ _thread = NEW_C_HEAP_ARRAY(GCTaskThread*, workers(), mtGC);
for (uint t = 0; t < workers(); t += 1) {
set_thread(t, GCTaskThread::create(this, t, processor_assignment[t]));
}
@@ -426,7 +426,7 @@
}
tty->cr();
}
- FREE_C_HEAP_ARRAY(uint, processor_assignment);
+ FREE_C_HEAP_ARRAY(uint, processor_assignment, mtGC);
}
reset_busy_workers();
set_unblocked();
@@ -455,11 +455,11 @@
GCTaskThread::destroy(thread(i));
set_thread(i, NULL);
}
- FREE_C_HEAP_ARRAY(GCTaskThread*, _thread);
+ FREE_C_HEAP_ARRAY(GCTaskThread*, _thread, mtGC);
_thread = NULL;
}
if (_resource_flag != NULL) {
- FREE_C_HEAP_ARRAY(bool, _resource_flag);
+ FREE_C_HEAP_ARRAY(bool, _resource_flag, mtGC);
_resource_flag = NULL;
}
if (queue() != NULL) {
@@ -817,7 +817,7 @@
}
NoopGCTask* NoopGCTask::create_on_c_heap() {
- NoopGCTask* result = new(ResourceObj::C_HEAP) NoopGCTask(true);
+ NoopGCTask* result = new(ResourceObj::C_HEAP, mtGC) NoopGCTask(true);
return result;
}
@@ -848,7 +848,7 @@
}
IdleGCTask* IdleGCTask::create_on_c_heap() {
- IdleGCTask* result = new(ResourceObj::C_HEAP) IdleGCTask(true);
+ IdleGCTask* result = new(ResourceObj::C_HEAP, mtGC) IdleGCTask(true);
assert(UseDynamicNumberOfGCThreads,
"Should only be used with dynamic GC thread");
return result;
@@ -984,7 +984,7 @@
WaitForBarrierGCTask* WaitForBarrierGCTask::create_on_c_heap() {
WaitForBarrierGCTask* result =
- new (ResourceObj::C_HEAP) WaitForBarrierGCTask(true);
+ new (ResourceObj::C_HEAP, mtGC) WaitForBarrierGCTask(true);
return result;
}
@@ -1114,7 +1114,7 @@
// Lazy initialization.
if (freelist() == NULL) {
_freelist =
- new(ResourceObj::C_HEAP) GrowableArray<Monitor*>(ParallelGCThreads,
+ new(ResourceObj::C_HEAP, mtGC) GrowableArray<Monitor*>(ParallelGCThreads,
true);
}
if (! freelist()->is_empty()) {
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -216,7 +216,7 @@
// A GCTaskQueue that can be synchronized.
// This "has-a" GCTaskQueue and a mutex to do the exclusion.
-class SynchronizedGCTaskQueue : public CHeapObj {
+class SynchronizedGCTaskQueue : public CHeapObj<mtGC> {
private:
// Instance state.
GCTaskQueue* _unsynchronized_queue; // Has-a unsynchronized queue.
@@ -278,7 +278,7 @@
// This is an abstract base class for getting notifications
// when a GCTaskManager is done.
-class NotifyDoneClosure : public CHeapObj {
+class NotifyDoneClosure : public CHeapObj<mtGC> {
public:
// The notification callback method.
virtual void notify(GCTaskManager* manager) = 0;
@@ -355,7 +355,7 @@
// held in the GCTaskThread** _thread array in GCTaskManager.
-class GCTaskManager : public CHeapObj {
+class GCTaskManager : public CHeapObj<mtGC> {
friend class ParCompactionManager;
friend class PSParallelCompact;
friend class PSScavenge;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -46,7 +46,7 @@
vm_exit_out_of_memory(0, "Cannot create GC thread. Out of system resources.");
if (PrintGCTaskTimeStamps) {
- _time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries );
+ _time_stamps = NEW_C_HEAP_ARRAY(GCTaskTimeStamp, GCTaskTimeStampEntries, mtGC);
guarantee(_time_stamps != NULL, "Sanity");
}
@@ -56,7 +56,7 @@
GCTaskThread::~GCTaskThread() {
if (_time_stamps != NULL) {
- FREE_C_HEAP_ARRAY(GCTaskTimeStamp, _time_stamps);
+ FREE_C_HEAP_ARRAY(GCTaskTimeStamp, _time_stamps, mtGC);
}
}
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskThread.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -90,7 +90,7 @@
void set_is_working(bool v) { _is_working = v; }
};
-class GCTaskTimeStamp : public CHeapObj
+class GCTaskTimeStamp : public CHeapObj<mtGC>
{
private:
jlong _entry_time;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -28,6 +28,7 @@
#include "memory/cardTableModRefBS.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/java.hpp"
+#include "services/memTracker.hpp"
void ObjectStartArray::initialize(MemRegion reserved_region) {
// We're based on the assumption that we use the same
@@ -50,6 +51,7 @@
if (!backing_store.is_reserved()) {
vm_exit_during_initialization("Could not reserve space for ObjectStartArray");
}
+ MemTracker::record_virtual_memory_type((address)backing_store.base(), mtGC);
// We do not commit any memory initially
if (!_virtual_space.initialize(backing_store, 0)) {
@@ -57,10 +59,14 @@
}
_raw_base = (jbyte*)_virtual_space.low_boundary();
+
if (_raw_base == NULL) {
vm_exit_during_initialization("Could not get raw_base address");
}
+ MemTracker::record_virtual_memory_type((address)_raw_base, mtGC);
+
+
_offset_base = _raw_base - (size_t(reserved_region.start()) >> block_shift);
_covered_region.set_start(reserved_region.start());
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/objectStartArray.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
// covered region.
//
-class ObjectStartArray : public CHeapObj {
+class ObjectStartArray : public CHeapObj<mtGC> {
friend class VerifyObjectStartArrayClosure;
private:
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -29,6 +29,7 @@
#include "oops/oop.inline.hpp"
#include "runtime/os.hpp"
#include "utilities/bitMap.inline.hpp"
+#include "services/memTracker.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
@@ -61,6 +62,9 @@
ReservedSpace rs(bytes, rs_align, rs_align > 0);
os::trace_page_sizes("par bitmap", raw_bytes, raw_bytes, page_sz,
rs.base(), rs.size());
+
+ MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
+
_virtual_space = new PSVirtualSpace(rs, page_sz);
if (_virtual_space != NULL && _virtual_space->expand_by(bytes)) {
_region_start = covered_region.start();
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -32,7 +32,7 @@
class oopDesc;
class ParMarkBitMapClosure;
-class ParMarkBitMap: public CHeapObj
+class ParMarkBitMap: public CHeapObj<mtGC>
{
public:
typedef BitMap::idx_t idx_t;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,6 +40,7 @@
#include "runtime/handles.inline.hpp"
#include "runtime/java.hpp"
#include "runtime/vmThread.hpp"
+#include "services/memTracker.hpp"
#include "utilities/vmError.hpp"
PSYoungGen* ParallelScavengeHeap::_young_gen = NULL;
@@ -161,6 +162,8 @@
}
}
+ MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtJavaHeap);
+
os::trace_page_sizes("ps perm", pg_min_size, pg_max_size, pg_page_sz,
heap_rs.base(), pg_max_size);
os::trace_page_sizes("ps main", og_min_size + yg_min_size,
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -81,14 +81,14 @@
uint parallel_gc_threads = PSParallelCompact::gc_task_manager()->workers();
assert(_manager_array == NULL, "Attempt to initialize twice");
- _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1 );
+ _manager_array = NEW_C_HEAP_ARRAY(ParCompactionManager*, parallel_gc_threads+1, mtGC);
guarantee(_manager_array != NULL, "Could not allocate manager_array");
_region_list = NEW_C_HEAP_ARRAY(RegionTaskQueue*,
- parallel_gc_threads+1);
+ parallel_gc_threads+1, mtGC);
guarantee(_region_list != NULL, "Could not initialize promotion manager");
- _recycled_stack_index = NEW_C_HEAP_ARRAY(uint, parallel_gc_threads);
+ _recycled_stack_index = NEW_C_HEAP_ARRAY(uint, parallel_gc_threads, mtGC);
// parallel_gc-threads + 1 to be consistent with the number of
// compaction managers.
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psCompactionManager.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -41,7 +41,7 @@
class ParallelCompactData;
class ParMarkBitMap;
-class ParCompactionManager : public CHeapObj {
+class ParCompactionManager : public CHeapObj<mtGC> {
friend class ParallelTaskTerminator;
friend class ParMarkBitMap;
friend class PSParallelCompact;
@@ -66,8 +66,8 @@
private:
// 32-bit: 4K * 8 = 32KiB; 64-bit: 8K * 16 = 128KiB
#define QUEUE_SIZE (1 << NOT_LP64(12) LP64_ONLY(13))
- typedef OverflowTaskQueue<ObjArrayTask, QUEUE_SIZE> ObjArrayTaskQueue;
- typedef GenericTaskQueueSet<ObjArrayTaskQueue> ObjArrayTaskQueueSet;
+ typedef OverflowTaskQueue<ObjArrayTask, mtGC, QUEUE_SIZE> ObjArrayTaskQueue;
+ typedef GenericTaskQueueSet<ObjArrayTaskQueue, mtGC> ObjArrayTaskQueueSet;
#undef QUEUE_SIZE
static ParCompactionManager** _manager_array;
@@ -78,7 +78,7 @@
static PSOldGen* _old_gen;
private:
- OverflowTaskQueue<oop> _marking_stack;
+ OverflowTaskQueue<oop, mtGC> _marking_stack;
ObjArrayTaskQueue _objarray_stack;
// Is there a way to reuse the _marking_stack for the
@@ -110,8 +110,8 @@
// popped. If -1, there has not been any entry popped.
static int _recycled_bottom;
- Stack<Klass*> _revisit_klass_stack;
- Stack<DataLayout*> _revisit_mdo_stack;
+ Stack<Klass*, mtGC> _revisit_klass_stack;
+ Stack<DataLayout*, mtGC> _revisit_mdo_stack;
static ParMarkBitMap* _mark_bitmap;
@@ -126,7 +126,7 @@
protected:
// Array of tasks. Needed by the ParallelTaskTerminator.
static RegionTaskQueueSet* region_array() { return _region_array; }
- OverflowTaskQueue<oop>* marking_stack() { return &_marking_stack; }
+ OverflowTaskQueue<oop, mtGC>* marking_stack() { return &_marking_stack; }
// Pushes onto the marking stack. If the marking stack is full,
// pushes onto the overflow stack.
@@ -175,8 +175,8 @@
bool should_update();
bool should_copy();
- Stack<Klass*>* revisit_klass_stack() { return &_revisit_klass_stack; }
- Stack<DataLayout*>* revisit_mdo_stack() { return &_revisit_mdo_stack; }
+ Stack<Klass*, mtGC>* revisit_klass_stack() { return &_revisit_klass_stack; }
+ Stack<DataLayout*, mtGC>* revisit_mdo_stack() { return &_revisit_mdo_stack; }
// Save for later processing. Must not fail.
inline void push(oop obj) { _marking_stack.push(obj); }
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGenerationCounters.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psGenerationCounters.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
const char* cns = PerfDataManager::name_space("generation", ordinal);
- _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1);
+ _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
strcpy(_name_space, cns);
const char* cname = PerfDataManager::counter_name(_name_space, "name");
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
class ObjectStartArray;
-class PSMarkSweepDecorator: public CHeapObj {
+class PSMarkSweepDecorator: public CHeapObj<mtGC> {
private:
static PSMarkSweepDecorator* _destination_decorator;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psOldGen.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
class PSMarkSweepDecorator;
-class PSOldGen : public CHeapObj {
+class PSOldGen : public CHeapObj<mtGC> {
friend class VMStructs;
friend class PSPromotionManager; // Uses the cas_allocate methods
friend class ParallelScavengeHeap;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -53,6 +53,7 @@
#include "runtime/vmThread.hpp"
#include "services/management.hpp"
#include "services/memoryService.hpp"
+#include "services/memTracker.hpp"
#include "utilities/events.hpp"
#include "utilities/stack.inline.hpp"
@@ -405,6 +406,9 @@
ReservedSpace rs(bytes, rs_align, rs_align > 0);
os::trace_page_sizes("par compact", raw_bytes, raw_bytes, page_sz, rs.base(),
rs.size());
+
+ MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
+
PSVirtualSpace* vspace = new PSVirtualSpace(rs, page_sz);
if (vspace != 0) {
if (vspace->expand_by(bytes)) {
@@ -2732,7 +2736,7 @@
for (uint i = 0; i < ParallelGCThreads + 1; i++) {
ParCompactionManager* cm = ParCompactionManager::manager_array(i);
KeepAliveClosure keep_alive_closure(cm);
- Stack<Klass*>* const rks = cm->revisit_klass_stack();
+ Stack<Klass*, mtGC>* const rks = cm->revisit_klass_stack();
if (PrintRevisitStats) {
gclog_or_tty->print_cr("Revisit klass stack[%u] length = " SIZE_FORMAT,
i, rks->size());
@@ -2765,7 +2769,7 @@
}
for (uint i = 0; i < ParallelGCThreads + 1; i++) {
ParCompactionManager* cm = ParCompactionManager::manager_array(i);
- Stack<DataLayout*>* rms = cm->revisit_mdo_stack();
+ Stack<DataLayout*, mtGC>* rms = cm->revisit_mdo_stack();
if (PrintRevisitStats) {
gclog_or_tty->print_cr("Revisit MDO stack[%u] size = " SIZE_FORMAT,
i, rms->size());
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,7 +36,7 @@
class ObjectStartArray;
-class PSPromotionLAB : public CHeapObj {
+class PSPromotionLAB : public CHeapObj<mtGC> {
protected:
static size_t filler_header_size;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -45,7 +45,7 @@
_young_space = heap->young_gen()->to_space();
assert(_manager_array == NULL, "Attempt to initialize twice");
- _manager_array = NEW_C_HEAP_ARRAY(PSPromotionManager*, ParallelGCThreads+1 );
+ _manager_array = NEW_C_HEAP_ARRAY(PSPromotionManager*, ParallelGCThreads+1, mtGC);
guarantee(_manager_array != NULL, "Could not initialize promotion manager");
_stack_array_depth = new OopStarTaskQueueSet(ParallelGCThreads);
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -49,7 +49,7 @@
class PSOldGen;
class ParCompactionManager;
-class PSPromotionManager : public CHeapObj {
+class PSPromotionManager : public CHeapObj<mtGC> {
friend class PSScavenge;
friend class PSRefProcTaskExecutor;
private:
@@ -77,7 +77,7 @@
bool _old_gen_is_full;
OopStarTaskQueue _claimed_stack_depth;
- OverflowTaskQueue<oop> _claimed_stack_breadth;
+ OverflowTaskQueue<oop, mtGC> _claimed_stack_breadth;
bool _totally_drain;
uint _target_stack_size;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -62,8 +62,8 @@
int PSScavenge::_tenuring_threshold = 0;
HeapWord* PSScavenge::_young_generation_boundary = NULL;
elapsedTimer PSScavenge::_accumulated_time;
-Stack<markOop> PSScavenge::_preserved_mark_stack;
-Stack<oop> PSScavenge::_preserved_oop_stack;
+Stack<markOop, mtGC> PSScavenge::_preserved_mark_stack;
+Stack<oop, mtGC> PSScavenge::_preserved_oop_stack;
CollectorCounters* PSScavenge::_counters = NULL;
bool PSScavenge::_promotion_failed = false;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -71,8 +71,8 @@
static HeapWord* _young_generation_boundary; // The lowest address possible for the young_gen.
// This is used to decide if an oop should be scavenged,
// cards should be marked, etc.
- static Stack<markOop> _preserved_mark_stack; // List of marks to be restored after failed promotion
- static Stack<oop> _preserved_oop_stack; // List of oops that need their mark restored.
+ static Stack<markOop, mtGC> _preserved_mark_stack; // List of marks to be restored after failed promotion
+ static Stack<oop, mtGC> _preserved_oop_stack; // List of oops that need their mark restored.
static CollectorCounters* _counters; // collector performance counters
static bool _promotion_failed;
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psVirtualspace.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -32,7 +32,7 @@
// VirtualSpace is data structure for committing a previously reserved address
// range in smaller chunks.
-class PSVirtualSpace : public CHeapObj {
+class PSVirtualSpace : public CHeapObj<mtGC> {
friend class VMStructs;
protected:
// The space is committed/uncommited in chunks of size _alignment. The
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psYoungGen.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,7 +33,7 @@
class PSMarkSweepDecorator;
-class PSYoungGen : public CHeapObj {
+class PSYoungGen : public CHeapObj<mtGC> {
friend class VMStructs;
friend class ParallelScavengeHeap;
friend class AdjoiningGenerations;
--- a/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/adaptiveSizePolicy.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -38,7 +38,7 @@
class elapsedTimer;
class CollectorPolicy;
-class AdaptiveSizePolicy : public CHeapObj {
+class AdaptiveSizePolicy : public CHeapObj<mtGC> {
friend class GCAdaptivePolicyCounters;
friend class PSGCAdaptivePolicyCounters;
friend class CMSGCAdaptivePolicyCounters;
--- a/hotspot/src/share/vm/gc_implementation/shared/cSpaceCounters.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/cSpaceCounters.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -37,7 +37,7 @@
const char* cns = PerfDataManager::name_space(gc->name_space(), "space",
ordinal);
- _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1);
+ _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
strcpy(_name_space, cns);
const char* cname = PerfDataManager::counter_name(_name_space, "name");
--- a/hotspot/src/share/vm/gc_implementation/shared/cSpaceCounters.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/cSpaceCounters.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -32,7 +32,7 @@
// A CSpaceCounters is a holder class for performance counters
// that track a space;
-class CSpaceCounters: public CHeapObj {
+class CSpaceCounters: public CHeapObj<mtGC> {
friend class VMStructs;
private:
@@ -52,7 +52,7 @@
ContiguousSpace* s, GenerationCounters* gc);
~CSpaceCounters() {
- if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+ if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space, mtInternal);
}
inline void update_capacity() {
--- a/hotspot/src/share/vm/gc_implementation/shared/collectorCounters.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/collectorCounters.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
const char* cns = PerfDataManager::name_space("collector", ordinal);
- _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1);
+ _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
strcpy(_name_space, cns);
char* cname = PerfDataManager::counter_name(_name_space, "name");
--- a/hotspot/src/share/vm/gc_implementation/shared/collectorCounters.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/collectorCounters.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -30,7 +30,7 @@
// CollectorCounters is a holder class for performance counters
// that track a collector
-class CollectorCounters: public CHeapObj {
+class CollectorCounters: public CHeapObj<mtGC> {
friend class VMStructs;
private:
@@ -50,7 +50,7 @@
CollectorCounters(const char* name, int ordinal);
~CollectorCounters() {
- if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+ if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space, mtGC);
}
inline PerfCounter* invocation_counter() const { return _invocations; }
--- a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -41,7 +41,7 @@
const char* cns = PerfDataManager::name_space(gc->name_space(), "space",
ordinal);
- _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1);
+ _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
strcpy(_name_space, cns);
const char* cname = PerfDataManager::counter_name(_name_space, "name");
--- a/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gSpaceCounters.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
// A GSpaceCounter is a holder class for performance counters
// that track a space;
-class GSpaceCounters: public CHeapObj {
+class GSpaceCounters: public CHeapObj<mtGC> {
friend class VMStructs;
private:
@@ -54,7 +54,7 @@
GenerationCounters* gc, bool sampled=true);
~GSpaceCounters() {
- if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+ if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space, mtGC);
}
inline void update_capacity() {
--- a/hotspot/src/share/vm/gc_implementation/shared/gcPolicyCounters.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcPolicyCounters.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -30,7 +30,7 @@
// GCPolicyCounters is a holder class for performance counters
// that track a generation
-class GCPolicyCounters: public CHeapObj {
+class GCPolicyCounters: public CHeapObj<mtGC> {
friend class VMStructs;
private:
--- a/hotspot/src/share/vm/gc_implementation/shared/gcStats.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcStats.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -27,7 +27,7 @@
#include "gc_implementation/shared/gcUtil.hpp"
-class GCStats : public CHeapObj {
+class GCStats : public CHeapObj<mtGC> {
protected:
// Avg amount promoted; used for avoiding promotion undo
// This class does not update deviations if the sample is zero.
--- a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -43,7 +43,7 @@
//
// This serves as our best estimate of a future unknown.
//
-class AdaptiveWeightedAverage : public CHeapObj {
+class AdaptiveWeightedAverage : public CHeapObj<mtGC> {
private:
float _average; // The last computed average
unsigned _sample_count; // How often we've sampled this average
@@ -146,7 +146,7 @@
// Placement support
void* operator new(size_t ignored, void* p) { return p; }
// Allocator
- void* operator new(size_t size) { return CHeapObj::operator new(size); }
+ void* operator new(size_t size) { return CHeapObj<mtGC>::operator new(size); }
// Accessor
float padded_average() const { return _padded_avg; }
@@ -192,7 +192,7 @@
// equation.
// y = intercept + slope * x
-class LinearLeastSquareFit : public CHeapObj {
+class LinearLeastSquareFit : public CHeapObj<mtGC> {
double _sum_x; // sum of all independent data points x
double _sum_x_squared; // sum of all independent data points x**2
double _sum_y; // sum of all dependent data points y
--- a/hotspot/src/share/vm/gc_implementation/shared/generationCounters.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/generationCounters.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
const char* cns = PerfDataManager::name_space("generation", ordinal);
- _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1);
+ _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
strcpy(_name_space, cns);
const char* cname = PerfDataManager::counter_name(_name_space, "name");
--- a/hotspot/src/share/vm/gc_implementation/shared/generationCounters.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/generationCounters.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -31,7 +31,7 @@
// A GenerationCounter is a holder class for performance counters
// that track a generation
-class GenerationCounters: public CHeapObj {
+class GenerationCounters: public CHeapObj<mtGC> {
friend class VMStructs;
private:
@@ -69,7 +69,7 @@
VirtualSpace* v);
~GenerationCounters() {
- if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+ if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space, mtGC);
}
virtual void update_all();
--- a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
const char* cns =
PerfDataManager::name_space(gc->name_space(), "space", ordinal);
- _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1);
+ _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
strcpy(_name_space, cns);
const char* cname = PerfDataManager::counter_name(_name_space, "name");
--- a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -37,7 +37,7 @@
class HeapSpaceUsedHelper;
class G1SpaceMonitoringSupport;
-class HSpaceCounters: public CHeapObj {
+class HSpaceCounters: public CHeapObj<mtGC> {
friend class VMStructs;
private:
@@ -55,7 +55,7 @@
size_t initial_capacity, GenerationCounters* gc);
~HSpaceCounters() {
- if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+ if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space, mtGC);
}
inline void update_capacity(size_t v) {
--- a/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/immutableSpace.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,7 +33,7 @@
// Invariant: bottom() and end() are on page_size boundaries and
// bottom() <= end()
-class ImmutableSpace: public CHeapObj {
+class ImmutableSpace: public CHeapObj<mtGC> {
friend class VMStructs;
protected:
HeapWord* _bottom;
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -30,13 +30,13 @@
#include "oops/objArrayKlass.inline.hpp"
#include "oops/oop.inline.hpp"
-Stack<oop> MarkSweep::_marking_stack;
-Stack<DataLayout*> MarkSweep::_revisit_mdo_stack;
-Stack<Klass*> MarkSweep::_revisit_klass_stack;
-Stack<ObjArrayTask> MarkSweep::_objarray_stack;
+Stack<oop, mtGC> MarkSweep::_marking_stack;
+Stack<DataLayout*, mtGC> MarkSweep::_revisit_mdo_stack;
+Stack<Klass*, mtGC> MarkSweep::_revisit_klass_stack;
+Stack<ObjArrayTask, mtGC> MarkSweep::_objarray_stack;
-Stack<oop> MarkSweep::_preserved_oop_stack;
-Stack<markOop> MarkSweep::_preserved_mark_stack;
+Stack<oop, mtGC> MarkSweep::_preserved_oop_stack;
+Stack<markOop, mtGC> MarkSweep::_preserved_mark_stack;
size_t MarkSweep::_preserved_count = 0;
size_t MarkSweep::_preserved_count_max = 0;
PreservedMark* MarkSweep::_preserved_marks = NULL;
@@ -166,7 +166,7 @@
}
// deal with the overflow stack
- StackIterator<oop> iter(_preserved_oop_stack);
+ StackIterator<oop, mtGC> iter(_preserved_oop_stack);
while (!iter.is_empty()) {
oop* p = iter.next_addr();
adjust_pointer(p);
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -122,16 +122,16 @@
//
protected:
// Traversal stacks used during phase1
- static Stack<oop> _marking_stack;
- static Stack<ObjArrayTask> _objarray_stack;
+ static Stack<oop, mtGC> _marking_stack;
+ static Stack<ObjArrayTask, mtGC> _objarray_stack;
// Stack for live klasses to revisit at end of marking phase
- static Stack<Klass*> _revisit_klass_stack;
+ static Stack<Klass*, mtGC> _revisit_klass_stack;
// Set (stack) of MDO's to revisit at end of marking phase
- static Stack<DataLayout*> _revisit_mdo_stack;
+ static Stack<DataLayout*, mtGC> _revisit_mdo_stack;
// Space for storing/restoring mark word
- static Stack<markOop> _preserved_mark_stack;
- static Stack<oop> _preserved_oop_stack;
+ static Stack<markOop, mtGC> _preserved_mark_stack;
+ static Stack<oop, mtGC> _preserved_oop_stack;
static size_t _preserved_count;
static size_t _preserved_count_max;
static PreservedMark* _preserved_marks;
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -43,7 +43,7 @@
MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment) {
- _lgrp_spaces = new (ResourceObj::C_HEAP) GrowableArray<LGRPSpace*>(0, true);
+ _lgrp_spaces = new (ResourceObj::C_HEAP, mtGC) GrowableArray<LGRPSpace*>(0, true);
_page_size = os::vm_page_size();
_adaptation_cycles = 0;
_samples_count = 0;
@@ -231,7 +231,7 @@
if (force || changed) {
// Compute lgrp intersection. Add/remove spaces.
int lgrp_limit = (int)os::numa_get_groups_num();
- int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit);
+ int *lgrp_ids = NEW_C_HEAP_ARRAY(int, lgrp_limit, mtGC);
int lgrp_num = (int)os::numa_get_leaf_groups(lgrp_ids, lgrp_limit);
assert(lgrp_num > 0, "There should be at least one locality group");
// Add new spaces for the new nodes
@@ -265,7 +265,7 @@
}
}
- FREE_C_HEAP_ARRAY(int, lgrp_ids);
+ FREE_C_HEAP_ARRAY(int, lgrp_ids, mtGC);
if (changed) {
for (JavaThread *thread = Threads::first(); thread; thread = thread->next()) {
--- a/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/mutableNUMASpace.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -63,7 +63,7 @@
class MutableNUMASpace : public MutableSpace {
friend class VMStructs;
- class LGRPSpace : public CHeapObj {
+ class LGRPSpace : public CHeapObj<mtGC> {
int _lgrp_id;
MutableSpace* _space;
MemRegion _invalid_region;
--- a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -39,7 +39,7 @@
const char* cns = PerfDataManager::name_space(gc->name_space(), "space",
ordinal);
- _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1);
+ _name_space = NEW_C_HEAP_ARRAY(char, strlen(cns)+1, mtGC);
strcpy(_name_space, cns);
const char* cname = PerfDataManager::counter_name(_name_space, "name");
--- a/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/spaceCounters.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
// A SpaceCounter is a holder class for performance counters
// that track a space;
-class SpaceCounters: public CHeapObj {
+class SpaceCounters: public CHeapObj<mtGC> {
friend class VMStructs;
private:
@@ -55,7 +55,7 @@
MutableSpace* m, GenerationCounters* gc);
~SpaceCounters() {
- if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space);
+ if (_name_space != NULL) FREE_C_HEAP_ARRAY(char, _name_space, mtGC);
}
inline void update_capacity() {
--- a/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_implementation/shared/spaceDecorator.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -70,7 +70,7 @@
// These subclasses abstract the differences in the types of spaces used
// by each heap.
-class SpaceMangler: public CHeapObj {
+class SpaceMangler: public CHeapObj<mtGC> {
friend class VMStructs;
// High water mark for allocations. Typically, the space above
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -74,7 +74,7 @@
// G1CollectedHeap
// ParallelScavengeHeap
//
-class CollectedHeap : public CHeapObj {
+class CollectedHeap : public CHeapObj<mtInternal> {
friend class VMStructs;
friend class IsGCActiveMark; // Block structured external access to _is_gc_active
friend class constantPoolCacheKlass; // allocate() method inserts is_conc_safe
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1118,8 +1118,8 @@
SignatureHandlerLibrary::buffer_size);
_buffer = bb->code_begin();
- _fingerprints = new(ResourceObj::C_HEAP)GrowableArray<uint64_t>(32, true);
- _handlers = new(ResourceObj::C_HEAP)GrowableArray<address>(32, true);
+ _fingerprints = new(ResourceObj::C_HEAP, mtCode)GrowableArray<uint64_t>(32, true);
+ _handlers = new(ResourceObj::C_HEAP, mtCode)GrowableArray<address>(32, true);
}
address SignatureHandlerLibrary::set_handler(CodeBuffer* buffer) {
--- a/hotspot/src/share/vm/interpreter/oopMapCache.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/oopMapCache.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -348,7 +348,7 @@
if (mask_size() > small_mask_limit) {
assert(_bit_mask[0] == 0, "bit mask should be new or just flushed");
_bit_mask[0] = (intptr_t)
- NEW_C_HEAP_ARRAY(uintptr_t, mask_word_size());
+ NEW_C_HEAP_ARRAY(uintptr_t, mask_word_size(), mtClass);
}
}
@@ -356,7 +356,7 @@
if (mask_size() > small_mask_limit && _bit_mask[0] != 0) {
assert(!Thread::current()->resource_area()->contains((void*)_bit_mask[0]),
"This bit mask should not be in the resource area");
- FREE_C_HEAP_ARRAY(uintptr_t, _bit_mask[0]);
+ FREE_C_HEAP_ARRAY(uintptr_t, _bit_mask[0], mtClass);
debug_only(_bit_mask[0] = 0;)
}
}
@@ -506,7 +506,7 @@
OopMapCache::OopMapCache() :
_mut(Mutex::leaf, "An OopMapCache lock", true)
{
- _array = NEW_C_HEAP_ARRAY(OopMapCacheEntry, _size);
+ _array = NEW_C_HEAP_ARRAY(OopMapCacheEntry, _size, mtClass);
// Cannot call flush for initialization, since flush
// will check if memory should be deallocated
for(int i = 0; i < _size; i++) _array[i].initialize();
@@ -520,7 +520,7 @@
flush();
// Deallocate array
NOT_PRODUCT(_total_memory_usage -= sizeof(OopMapCache) + (sizeof(OopMapCacheEntry) * _size);)
- FREE_C_HEAP_ARRAY(OopMapCacheEntry, _array);
+ FREE_C_HEAP_ARRAY(OopMapCacheEntry, _array, mtClass);
}
OopMapCacheEntry* OopMapCache::entry_at(int i) const {
@@ -639,9 +639,9 @@
void OopMapCache::compute_one_oop_map(methodHandle method, int bci, InterpreterOopMap* entry) {
// Due to the invariants above it's tricky to allocate a temporary OopMapCacheEntry on the stack
- OopMapCacheEntry* tmp = NEW_C_HEAP_ARRAY(OopMapCacheEntry, 1);
+ OopMapCacheEntry* tmp = NEW_C_HEAP_ARRAY(OopMapCacheEntry, 1, mtClass);
tmp->initialize();
tmp->fill(method, bci);
entry->resource_copy(tmp);
- FREE_C_HEAP_ARRAY(OopMapCacheEntry, tmp);
+ FREE_C_HEAP_ARRAY(OopMapCacheEntry, tmp, mtInternal);
}
--- a/hotspot/src/share/vm/interpreter/oopMapCache.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/oopMapCache.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -156,7 +156,7 @@
#endif
};
-class OopMapCache : public CHeapObj {
+class OopMapCache : public CHeapObj<mtClass> {
private:
enum { _size = 32, // Use fixed size for now
_probe_depth = 3 // probe depth in case of collisions
--- a/hotspot/src/share/vm/libadt/set.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/libadt/set.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -71,7 +71,7 @@
set.Sort(); // Sort elements for in-order retrieval
uint len = 128; // Total string space
- char *buf = NEW_C_HEAP_ARRAY(char,len);// Some initial string space
+ char *buf = NEW_C_HEAP_ARRAY(char,len, mtCompiler);// Some initial string space
register char *s = buf; // Current working string pointer
*s++ = '{';
@@ -86,7 +86,7 @@
if( buf+len-s < 25 ) { // Generous trailing space for upcoming numbers
int offset = (int)(s-buf);// Not enuf space; compute offset into buffer
len <<= 1; // Double string size
- buf = REALLOC_C_HEAP_ARRAY(char,buf,len); // Reallocate doubled size
+ buf = REALLOC_C_HEAP_ARRAY(char,buf,len, mtCompiler); // Reallocate doubled size
s = buf+offset; // Get working pointer into new bigger buffer
}
if( lo != (uint)-2 ) { // Startup? No! Then print previous range.
@@ -101,7 +101,7 @@
if( buf+len-s < 25 ) { // Generous trailing space for upcoming numbers
int offset = (int)(s-buf);// Not enuf space; compute offset into buffer
len <<= 1; // Double string size
- buf = (char*)ReallocateHeap(buf,len); // Reallocate doubled size
+ buf = (char*)ReallocateHeap(buf,len, mtCompiler); // Reallocate doubled size
s = buf+offset; // Get working pointer into new bigger buffer
}
if( lo != hi ) sprintf(s,"%d-%d}",lo,hi);
--- a/hotspot/src/share/vm/libadt/vectset.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/libadt/vectset.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -362,7 +362,7 @@
};
SetI_ *VectorSet::iterate(uint &elem) const {
- return new(ResourceObj::C_HEAP) VSetI_(this, elem);
+ return new(ResourceObj::C_HEAP, mtInternal) VSetI_(this, elem);
}
//=============================================================================
--- a/hotspot/src/share/vm/memory/allocation.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/allocation.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -26,10 +26,13 @@
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/resourceArea.hpp"
+#include "runtime/atomic.hpp"
#include "runtime/os.hpp"
#include "runtime/task.hpp"
#include "runtime/threadCritical.hpp"
+#include "services/memTracker.hpp"
#include "utilities/ostream.hpp"
+
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
@@ -43,32 +46,16 @@
# include "os_bsd.inline.hpp"
#endif
-void* CHeapObj::operator new(size_t size){
- return (void *) AllocateHeap(size, "CHeapObj-new");
-}
-
-void* CHeapObj::operator new (size_t size, const std::nothrow_t& nothrow_constant) {
- char* p = (char*) os::malloc(size);
-#ifdef ASSERT
- if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
-#endif
- return p;
-}
-
-void CHeapObj::operator delete(void* p){
- FreeHeap(p);
-}
-
void* StackObj::operator new(size_t size) { ShouldNotCallThis(); return 0; };
void StackObj::operator delete(void* p) { ShouldNotCallThis(); };
void* _ValueObj::operator new(size_t size) { ShouldNotCallThis(); return 0; };
void _ValueObj::operator delete(void* p) { ShouldNotCallThis(); };
-void* ResourceObj::operator new(size_t size, allocation_type type) {
+void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) {
address res;
switch (type) {
case C_HEAP:
- res = (address)AllocateHeap(size, "C_Heap: ResourceOBJ");
+ res = (address)AllocateHeap(size, flags, CALLER_PC);
DEBUG_ONLY(set_allocation_type(res, C_HEAP);)
break;
case RESOURCE_AREA:
@@ -184,7 +171,7 @@
// MT-safe pool of chunks to reduce malloc/free thrashing
// NB: not using Mutex because pools are used before Threads are initialized
-class ChunkPool {
+class ChunkPool: public CHeapObj<mtInternal> {
Chunk* _first; // first cached Chunk; its first word points to next chunk
size_t _num_chunks; // number of unused chunks in pool
size_t _num_used; // number of chunks currently checked out
@@ -210,14 +197,16 @@
ChunkPool(size_t size) : _size(size) { _first = NULL; _num_chunks = _num_used = 0; }
// Allocate a new chunk from the pool (might expand the pool)
- void* allocate(size_t bytes) {
+ _NOINLINE_ void* allocate(size_t bytes) {
assert(bytes == _size, "bad size");
void* p = NULL;
+ // No VM lock can be taken inside ThreadCritical lock, so os::malloc
+ // should be done outside ThreadCritical lock due to NMT
{ ThreadCritical tc;
_num_used++;
p = get_first();
- if (p == NULL) p = os::malloc(bytes);
}
+ if (p == NULL) p = os::malloc(bytes, mtChunk, CURRENT_PC);
if (p == NULL)
vm_exit_out_of_memory(bytes, "ChunkPool::allocate");
@@ -238,28 +227,34 @@
// Prune the pool
void free_all_but(size_t n) {
+ Chunk* cur = NULL;
+ Chunk* next;
+ {
// if we have more than n chunks, free all of them
ThreadCritical tc;
if (_num_chunks > n) {
// free chunks at end of queue, for better locality
- Chunk* cur = _first;
+ cur = _first;
for (size_t i = 0; i < (n - 1) && cur != NULL; i++) cur = cur->next();
if (cur != NULL) {
- Chunk* next = cur->next();
+ next = cur->next();
cur->set_next(NULL);
cur = next;
- // Free all remaining chunks
+ _num_chunks = n;
+ }
+ }
+ }
+
+ // Free all remaining chunks, outside of ThreadCritical
+ // to avoid deadlock with NMT
while(cur != NULL) {
next = cur->next();
- os::free(cur);
- _num_chunks--;
+ os::free(cur, mtChunk);
cur = next;
}
}
- }
- }
// Accessors to preallocated pool's
static ChunkPool* large_pool() { assert(_large_pool != NULL, "must be initialized"); return _large_pool; }
@@ -323,7 +318,7 @@
case Chunk::medium_size: return ChunkPool::medium_pool()->allocate(bytes);
case Chunk::init_size: return ChunkPool::small_pool()->allocate(bytes);
default: {
- void *p = os::malloc(bytes);
+ void *p = os::malloc(bytes, mtChunk, CALLER_PC);
if (p == NULL)
vm_exit_out_of_memory(bytes, "Chunk::new");
return p;
@@ -337,7 +332,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;
- default: os::free(c);
+ default: os::free(c, mtChunk);
}
}
@@ -374,6 +369,7 @@
}
//------------------------------Arena------------------------------------------
+NOT_PRODUCT(volatile jint Arena::_instance_count = 0;)
Arena::Arena(size_t init_size) {
size_t round_size = (sizeof (char *)) - 1;
@@ -382,6 +378,7 @@
_hwm = _chunk->bottom(); // Save the cached hwm, max
_max = _chunk->top();
set_size_in_bytes(init_size);
+ NOT_PRODUCT(Atomic::inc(&_instance_count);)
}
Arena::Arena() {
@@ -389,12 +386,15 @@
_hwm = _chunk->bottom(); // Save the cached hwm, max
_max = _chunk->top();
set_size_in_bytes(Chunk::init_size);
+ NOT_PRODUCT(Atomic::inc(&_instance_count);)
}
Arena::Arena(Arena *a) : _chunk(a->_chunk), _hwm(a->_hwm), _max(a->_max), _first(a->_first) {
set_size_in_bytes(a->size_in_bytes());
+ NOT_PRODUCT(Atomic::inc(&_instance_count);)
}
+
Arena *Arena::move_contents(Arena *copy) {
copy->destruct_contents();
copy->_chunk = _chunk;
@@ -409,6 +409,42 @@
Arena::~Arena() {
destruct_contents();
+ NOT_PRODUCT(Atomic::dec(&_instance_count);)
+}
+
+void* Arena::operator new(size_t size) {
+ assert(false, "Use dynamic memory type binding");
+ return NULL;
+}
+
+void* Arena::operator new (size_t size, const std::nothrow_t& nothrow_constant) {
+ assert(false, "Use dynamic memory type binding");
+ return NULL;
+}
+
+ // dynamic memory type binding
+void* Arena::operator new(size_t size, MEMFLAGS flags) {
+#ifdef ASSERT
+ void* p = (void*)AllocateHeap(size, flags|otArena, CALLER_PC);
+ if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
+ return p;
+#else
+ return (void *) AllocateHeap(size, flags|otArena, CALLER_PC);
+#endif
+}
+
+void* Arena::operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) {
+#ifdef ASSERT
+ void* p = os::malloc(size, flags|otArena, CALLER_PC);
+ if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
+ return p;
+#else
+ return os::malloc(size, flags|otArena, CALLER_PC);
+#endif
+}
+
+void Arena::operator delete(void* p) {
+ FreeHeap(p);
}
// Destroy this arenas contents and reset to empty
@@ -421,6 +457,14 @@
reset();
}
+// This is high traffic method, but many calls actually don't
+// change the size
+void Arena::set_size_in_bytes(size_t size) {
+ if (_size_in_bytes != size) {
+ _size_in_bytes = size;
+ MemTracker::record_arena_size((address)this, size);
+ }
+}
// Total of all Chunks in arena
size_t Arena::used() const {
@@ -448,7 +492,6 @@
if (_chunk == NULL) {
signal_out_of_memory(len * Chunk::aligned_overhead_size(), "Arena::grow");
}
-
if (k) k->set_next(_chunk); // Append new chunk to end of linked list
else _first = _chunk;
_hwm = _chunk->bottom(); // Save the cached hwm, max
@@ -538,7 +581,7 @@
assert(UseMallocOnly, "shouldn't call");
// use malloc, but save pointer in res. area for later freeing
char** save = (char**)internal_malloc_4(sizeof(char*));
- return (*save = (char*)os::malloc(size));
+ return (*save = (char*)os::malloc(size, mtChunk));
}
// for debugging with UseMallocOnly
--- a/hotspot/src/share/vm/memory/allocation.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/allocation.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,18 @@
#define ARENA_ALIGN_MASK (~((size_t)ARENA_ALIGN_M1))
#define ARENA_ALIGN(x) ((((size_t)(x)) + ARENA_ALIGN_M1) & ARENA_ALIGN_MASK)
+
+// noinline attribute
+#ifdef _WINDOWS
+ #define _NOINLINE_ __declspec(noinline)
+#else
+ #if __GNUC__ < 3 // gcc 2.x does not support noinline attribute
+ #define _NOINLINE_
+ #else
+ #define _NOINLINE_ __attribute__ ((noinline))
+ #endif
+#endif
+
// All classes in the virtual machine must be subclassed
// by one of the following allocation classes:
//
@@ -98,12 +110,72 @@
};
#endif
-class CHeapObj ALLOCATION_SUPER_CLASS_SPEC {
+
+/*
+ * MemoryType bitmap layout:
+ * | 16 15 14 13 12 11 10 09 | 08 07 06 05 | 04 03 02 01 |
+ * | memory type | object | reserved |
+ * | | type | |
+ */
+enum MemoryType {
+ // Memory type by sub systems. It occupies lower byte.
+ mtNone = 0x0000, // undefined
+ mtClass = 0x0100, // memory class for Java classes
+ mtThread = 0x0200, // memory for thread objects
+ mtThreadStack = 0x0300,
+ mtCode = 0x0400, // memory for generated code
+ mtGC = 0x0500, // memory for GC
+ mtCompiler = 0x0600, // memory for compiler
+ mtInternal = 0x0700, // memory used by VM, but does not belong to
+ // any of above categories, and not used for
+ // native memory tracking
+ mtOther = 0x0800, // memory not used by VM
+ mtSymbol = 0x0900, // symbol
+ mtNMT = 0x0A00, // memory used by native memory tracking
+ mtChunk = 0x0B00, // chunk that holds content of arenas
+ mtJavaHeap = 0x0C00, // Java heap
+ mtDontTrack = 0x0D00, // memory we donot or cannot track
+ mt_number_of_types = 0x000C, // number of memory types
+ mt_masks = 0x7F00,
+
+ // object type mask
+ otArena = 0x0010, // an arena object
+ otNMTRecorder = 0x0020, // memory recorder object
+ ot_masks = 0x00F0
+};
+
+#define IS_MEMORY_TYPE(flags, type) ((flags & mt_masks) == type)
+#define HAS_VALID_MEMORY_TYPE(flags)((flags & mt_masks) != mtNone)
+#define FLAGS_TO_MEMORY_TYPE(flags) (flags & mt_masks)
+
+#define IS_ARENA_OBJ(flags) ((flags & ot_masks) == otArena)
+#define IS_NMT_RECORDER(flags) ((flags & ot_masks) == otNMTRecorder)
+#define NMT_CAN_TRACK(flags) (!IS_NMT_RECORDER(flags) && !(IS_MEMORY_TYPE(flags, mtDontTrack)))
+
+typedef unsigned short MEMFLAGS;
+
+extern bool NMT_track_callsite;
+
+// debug build does not inline
+#if defined(_DEBUG_)
+ #define CURRENT_PC (NMT_track_callsite ? os::get_caller_pc(1) : 0)
+ #define CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0)
+ #define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(3) : 0)
+#else
+ #define CURRENT_PC (NMT_track_callsite? os::get_caller_pc(0) : 0)
+ #define CALLER_PC (NMT_track_callsite ? os::get_caller_pc(1) : 0)
+ #define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0)
+#endif
+
+
+
+template <MEMFLAGS F> class CHeapObj ALLOCATION_SUPER_CLASS_SPEC {
public:
- void* operator new(size_t size);
- void* operator new (size_t size, const std::nothrow_t& nothrow_constant);
+ _NOINLINE_ void* operator new(size_t size, address caller_pc = 0);
+ _NOINLINE_ void* operator new (size_t size, const std::nothrow_t& nothrow_constant,
+ address caller_pc = 0);
+
void operator delete(void* p);
- void* new_array(size_t size);
};
// Base class for objects allocated on the stack only.
@@ -150,7 +222,7 @@
//------------------------------Chunk------------------------------------------
// Linked list of raw memory chunks
-class Chunk: public CHeapObj {
+class Chunk: CHeapObj<mtChunk> {
friend class VMStructs;
protected:
@@ -197,7 +269,7 @@
//------------------------------Arena------------------------------------------
// Fast allocation of memory
-class Arena: public CHeapObj {
+class Arena : public CHeapObj<mtNone|otArena> {
protected:
friend class ResourceMark;
friend class HandleMark;
@@ -208,7 +280,8 @@
Chunk *_chunk; // current chunk
char *_hwm, *_max; // High water mark and max in current chunk
void* grow(size_t x); // Get a new Chunk of at least size x
- NOT_PRODUCT(size_t _size_in_bytes;) // Size of arena (used for memory usage tracing)
+ size_t _size_in_bytes; // Size of arena (used for native memory tracking)
+
NOT_PRODUCT(static julong _bytes_allocated;) // total #bytes allocated since start
friend class AllocStats;
debug_only(void* malloc(size_t size);)
@@ -231,6 +304,15 @@
void destruct_contents();
char* hwm() const { return _hwm; }
+ // new operators
+ void* operator new (size_t size);
+ void* operator new (size_t size, const std::nothrow_t& nothrow_constant);
+
+ // dynamic memory type tagging
+ void* operator new(size_t size, MEMFLAGS flags);
+ void* operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags);
+ void operator delete(void* p);
+
// Fast allocate in the arena. Common case is: pointer test + increment.
void* Amalloc(size_t x) {
assert(is_power_of_2(ARENA_AMALLOC_ALIGNMENT) , "should be a power of 2");
@@ -306,16 +388,20 @@
size_t used() const;
// Total # of bytes used
- size_t size_in_bytes() const NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0;
- void set_size_in_bytes(size_t size) NOT_PRODUCT({ _size_in_bytes = size; }) PRODUCT_RETURN;
+ size_t size_in_bytes() const { return _size_in_bytes; };
+ void set_size_in_bytes(size_t size);
+
static void free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2) PRODUCT_RETURN;
static void free_all(char** start, char** end) PRODUCT_RETURN;
+ // how many arena instances
+ NOT_PRODUCT(static volatile jint _instance_count;)
private:
// Reset this Arena to empty, access will trigger grow if necessary
void reset(void) {
_first = _chunk = NULL;
_hwm = _max = NULL;
+ set_size_in_bytes(0);
}
};
@@ -373,7 +459,7 @@
#endif // ASSERT
public:
- void* operator new(size_t size, allocation_type type);
+ void* operator new(size_t size, allocation_type type, MEMFLAGS flags);
void* operator new(size_t size, Arena *arena) {
address res = (address)arena->Amalloc(size);
DEBUG_ONLY(set_allocation_type(res, ARENA);)
@@ -409,17 +495,28 @@
#define NEW_RESOURCE_OBJ(type)\
NEW_RESOURCE_ARRAY(type, 1)
-#define NEW_C_HEAP_ARRAY(type, size)\
- (type*) (AllocateHeap((size) * sizeof(type), XSTR(type) " in " __FILE__))
+#define NEW_C_HEAP_ARRAY(type, size, memflags)\
+ (type*) (AllocateHeap((size) * sizeof(type), memflags))
-#define REALLOC_C_HEAP_ARRAY(type, old, size)\
- (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), XSTR(type) " in " __FILE__))
+#define REALLOC_C_HEAP_ARRAY(type, old, size, memflags)\
+ (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), memflags))
+
+#define FREE_C_HEAP_ARRAY(type,old,memflags) \
+ FreeHeap((char*)(old), memflags)
-#define FREE_C_HEAP_ARRAY(type,old) \
- FreeHeap((char*)(old))
+#define NEW_C_HEAP_OBJ(type, memflags)\
+ NEW_C_HEAP_ARRAY(type, 1, memflags)
+
+
+#define NEW_C_HEAP_ARRAY2(type, size, memflags, pc)\
+ (type*) (AllocateHeap((size) * sizeof(type), memflags, pc))
-#define NEW_C_HEAP_OBJ(type)\
- NEW_C_HEAP_ARRAY(type, 1)
+#define REALLOC_C_HEAP_ARRAY2(type, old, size, memflags, pc)\
+ (type*) (ReallocateHeap((char*)old, (size) * sizeof(type), memflags, pc))
+
+#define NEW_C_HEAP_OBJ2(type, memflags, pc)\
+ NEW_C_HEAP_ARRAY2(type, 1, memflags, pc)
+
extern bool warn_new_operator;
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/allocation.inline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -48,33 +48,60 @@
#endif
// allocate using malloc; will fail if no memory available
-inline char* AllocateHeap(size_t size, const char* name = NULL) {
- char* p = (char*) os::malloc(size);
+inline char* AllocateHeap(size_t size, MEMFLAGS flags, address pc = 0) {
+ if (pc == 0) {
+ pc = CURRENT_PC;
+ }
+ char* p = (char*) os::malloc(size, flags, pc);
#ifdef ASSERT
- if (PrintMallocFree) trace_heap_malloc(size, name, p);
- #else
- Unused_Variable(name);
+ if (PrintMallocFree) trace_heap_malloc(size, "AllocateHeap", p);
#endif
- if (p == NULL) vm_exit_out_of_memory(size, name);
+ if (p == NULL) vm_exit_out_of_memory(size, "AllocateHeap");
+ return p;
+}
+
+inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flags) {
+ char* p = (char*) os::realloc(old, size, flags, CURRENT_PC);
+ #ifdef ASSERT
+ if (PrintMallocFree) trace_heap_malloc(size, "ReallocateHeap", p);
+ #endif
+ if (p == NULL) vm_exit_out_of_memory(size, "ReallocateHeap");
return p;
}
-inline char* ReallocateHeap(char *old, size_t size, const char* name = NULL) {
- char* p = (char*) os::realloc(old,size);
- #ifdef ASSERT
- if (PrintMallocFree) trace_heap_malloc(size, name, p);
- #else
- Unused_Variable(name);
- #endif
- if (p == NULL) vm_exit_out_of_memory(size, name);
- return p;
-}
-
-inline void FreeHeap(void* p) {
+inline void FreeHeap(void* p, MEMFLAGS memflags = mtInternal) {
#ifdef ASSERT
if (PrintMallocFree) trace_heap_free(p);
#endif
- os::free(p);
+ os::free(p, memflags);
}
+
+template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size,
+ address caller_pc){
+#ifdef ASSERT
+ void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
+ if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
+ return p;
+#else
+ return (void *) AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
+#endif
+ }
+
+template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
+ const std::nothrow_t& nothrow_constant, address caller_pc) {
+#ifdef ASSERT
+ void* p = os::malloc(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
+ if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
+ return p;
+#else
+ return os::malloc(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
+#endif
+}
+
+template <MEMFLAGS F> void CHeapObj<F>::operator delete(void* p){
+ FreeHeap(p, F);
+}
+
+
#endif // SHARE_VM_MEMORY_ALLOCATION_INLINE_HPP
--- a/hotspot/src/share/vm/memory/barrierSet.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/barrierSet.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -31,7 +31,7 @@
// This class provides the interface between a barrier implementation and
// the rest of the system.
-class BarrierSet: public CHeapObj {
+class BarrierSet: public CHeapObj<mtGC> {
friend class VMStructs;
public:
enum Name {
--- a/hotspot/src/share/vm/memory/blockOffsetTable.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/blockOffsetTable.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -30,6 +30,7 @@
#include "memory/universe.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/java.hpp"
+#include "services/memTracker.hpp"
//////////////////////////////////////////////////////////////////////
// BlockOffsetSharedArray
@@ -44,6 +45,9 @@
if (!rs.is_reserved()) {
vm_exit_during_initialization("Could not reserve enough space for heap offset array");
}
+
+ MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
+
if (!_vs.initialize(rs, 0)) {
vm_exit_during_initialization("Could not reserve enough space for heap offset array");
}
--- a/hotspot/src/share/vm/memory/blockOffsetTable.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/blockOffsetTable.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -100,7 +100,7 @@
//////////////////////////////////////////////////////////////////////////
// BlockOffsetSharedArray
//////////////////////////////////////////////////////////////////////////
-class BlockOffsetSharedArray: public CHeapObj {
+class BlockOffsetSharedArray: public CHeapObj<mtGC> {
friend class BlockOffsetArray;
friend class BlockOffsetArrayNonContigSpace;
friend class BlockOffsetArrayContigSpace;
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,6 +33,7 @@
#include "runtime/java.hpp"
#include "runtime/mutexLocker.hpp"
#include "runtime/virtualspace.hpp"
+#include "services/memTracker.hpp"
#ifdef COMPILER1
#include "c1/c1_LIR.hpp"
#include "c1/c1_LIRGenerator.hpp"
@@ -90,6 +91,9 @@
const size_t rs_align = _page_size == (size_t) os::vm_page_size() ? 0 :
MAX2(_page_size, (size_t) os::vm_allocation_granularity());
ReservedSpace heap_rs(_byte_map_size, rs_align, false);
+
+ MemTracker::record_virtual_memory_type((address)heap_rs.base(), mtGC);
+
os::trace_page_sizes("card table", _guard_index + 1, _guard_index + 1,
_page_size, heap_rs.base(), heap_rs.size());
if (!heap_rs.is_reserved()) {
@@ -113,16 +117,17 @@
// Do better than this for Merlin
vm_exit_out_of_memory(_page_size, "card table last card");
}
+
*guard_card = last_card;
_lowest_non_clean =
- NEW_C_HEAP_ARRAY(CardArr, max_covered_regions);
+ NEW_C_HEAP_ARRAY(CardArr, max_covered_regions, mtGC);
_lowest_non_clean_chunk_size =
- NEW_C_HEAP_ARRAY(size_t, max_covered_regions);
+ NEW_C_HEAP_ARRAY(size_t, max_covered_regions, mtGC);
_lowest_non_clean_base_chunk_index =
- NEW_C_HEAP_ARRAY(uintptr_t, max_covered_regions);
+ NEW_C_HEAP_ARRAY(uintptr_t, max_covered_regions, mtGC);
_last_LNC_resizing_collection =
- NEW_C_HEAP_ARRAY(int, max_covered_regions);
+ NEW_C_HEAP_ARRAY(int, max_covered_regions, mtGC);
if (_lowest_non_clean == NULL
|| _lowest_non_clean_chunk_size == NULL
|| _lowest_non_clean_base_chunk_index == NULL
--- a/hotspot/src/share/vm/memory/collectorPolicy.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -56,7 +56,7 @@
class PermanentGenerationSpec;
class MarkSweepPolicy;
-class CollectorPolicy : public CHeapObj {
+class CollectorPolicy : public CHeapObj<mtGC> {
protected:
PermanentGenerationSpec *_permanent_generation;
GCPolicyCounters* _gc_policy_counters;
--- a/hotspot/src/share/vm/memory/defNewGeneration.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/defNewGeneration.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -89,8 +89,8 @@
// Together, these keep <object with a preserved mark, mark value> pairs.
// They should always contain the same number of elements.
- Stack<oop> _objs_with_preserved_marks;
- Stack<markOop> _preserved_marks_of_objs;
+ Stack<oop, mtGC> _objs_with_preserved_marks;
+ Stack<markOop, mtGC> _preserved_marks_of_objs;
// Promotion failure handling
OopClosure *_promo_failure_scan_stack_closure;
@@ -98,7 +98,7 @@
_promo_failure_scan_stack_closure = scan_stack_closure;
}
- Stack<oop> _promo_failure_scan_stack;
+ Stack<oop, mtGC> _promo_failure_scan_stack;
void drain_promo_failure_scan_stack(void);
bool _promo_failure_drain_in_progress;
--- a/hotspot/src/share/vm/memory/filemap.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/filemap.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -44,7 +44,7 @@
-class FileMapInfo : public CHeapObj {
+class FileMapInfo : public CHeapObj<mtInternal> {
private:
enum {
_invalid_version = -1,
--- a/hotspot/src/share/vm/memory/freeBlockDictionary.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/freeBlockDictionary.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,7 +34,7 @@
// A FreeBlockDictionary is an abstract superclass that will allow
// a number of alternative implementations in the future.
template <class Chunk>
-class FreeBlockDictionary: public CHeapObj {
+class FreeBlockDictionary: public CHeapObj<mtGC> {
public:
enum Dither {
atLeast,
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -203,21 +203,21 @@
#ifdef VALIDATE_MARK_SWEEP
if (ValidateMarkSweep) {
- _root_refs_stack = new (ResourceObj::C_HEAP) GrowableArray<void*>(100, true);
- _other_refs_stack = new (ResourceObj::C_HEAP) GrowableArray<void*>(100, true);
- _adjusted_pointers = new (ResourceObj::C_HEAP) GrowableArray<void*>(100, true);
- _live_oops = new (ResourceObj::C_HEAP) GrowableArray<oop>(100, true);
- _live_oops_moved_to = new (ResourceObj::C_HEAP) GrowableArray<oop>(100, true);
- _live_oops_size = new (ResourceObj::C_HEAP) GrowableArray<size_t>(100, true);
+ _root_refs_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<void*>(100, true);
+ _other_refs_stack = new (ResourceObj::C_HEAP, mtGC) GrowableArray<void*>(100, true);
+ _adjusted_pointers = new (ResourceObj::C_HEAP, mtGC) GrowableArray<void*>(100, true);
+ _live_oops = new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(100, true);
+ _live_oops_moved_to = new (ResourceObj::C_HEAP, mtGC) GrowableArray<oop>(100, true);
+ _live_oops_size = new (ResourceObj::C_HEAP, mtGC) GrowableArray<size_t>(100, true);
}
if (RecordMarkSweepCompaction) {
if (_cur_gc_live_oops == NULL) {
- _cur_gc_live_oops = new(ResourceObj::C_HEAP) GrowableArray<HeapWord*>(100, true);
- _cur_gc_live_oops_moved_to = new(ResourceObj::C_HEAP) GrowableArray<HeapWord*>(100, true);
- _cur_gc_live_oops_size = new(ResourceObj::C_HEAP) GrowableArray<size_t>(100, true);
- _last_gc_live_oops = new(ResourceObj::C_HEAP) GrowableArray<HeapWord*>(100, true);
- _last_gc_live_oops_moved_to = new(ResourceObj::C_HEAP) GrowableArray<HeapWord*>(100, true);
- _last_gc_live_oops_size = new(ResourceObj::C_HEAP) GrowableArray<size_t>(100, true);
+ _cur_gc_live_oops = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
+ _cur_gc_live_oops_moved_to = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
+ _cur_gc_live_oops_size = new(ResourceObj::C_HEAP, mtGC) GrowableArray<size_t>(100, true);
+ _last_gc_live_oops = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
+ _last_gc_live_oops_moved_to = new(ResourceObj::C_HEAP, mtGC) GrowableArray<HeapWord*>(100, true);
+ _last_gc_live_oops_size = new(ResourceObj::C_HEAP, mtGC) GrowableArray<size_t>(100, true);
} else {
_cur_gc_live_oops->clear();
_cur_gc_live_oops_moved_to->clear();
--- a/hotspot/src/share/vm/memory/genOopClosures.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/genOopClosures.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -34,10 +34,10 @@
class CardTableModRefBS;
class DefNewGeneration;
-template<class E, unsigned int N> class GenericTaskQueue;
-typedef GenericTaskQueue<oop, TASKQUEUE_SIZE> OopTaskQueue;
-template<class T> class GenericTaskQueueSet;
-typedef GenericTaskQueueSet<OopTaskQueue> OopTaskQueueSet;
+template<class E, MEMFLAGS F, unsigned int N> class GenericTaskQueue;
+typedef GenericTaskQueue<oop, mtGC, TASKQUEUE_SIZE> OopTaskQueue;
+template<class T, MEMFLAGS F> class GenericTaskQueueSet;
+typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
// Closure for iterating roots from a particular generation
// Note: all classes deriving from this MUST call this do_barrier
--- a/hotspot/src/share/vm/memory/genRemSet.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/genRemSet.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
class OopsInGenClosure;
class CardTableRS;
-class GenRemSet: public CHeapObj {
+class GenRemSet: public CHeapObj<mtGC> {
friend class Generation;
BarrierSet* _bs;
--- a/hotspot/src/share/vm/memory/generation.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/generation.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -86,7 +86,7 @@
};
-class Generation: public CHeapObj {
+class Generation: public CHeapObj<mtGC> {
friend class VMStructs;
private:
jlong _time_of_last_gc; // time when last gc on this generation happened (ms)
--- a/hotspot/src/share/vm/memory/generationSpec.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/generationSpec.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -32,7 +32,7 @@
// some generation-specific behavior. This is done here rather than as a
// virtual function of Generation because these methods are needed in
// initialization of the Generations.
-class GenerationSpec : public CHeapObj {
+class GenerationSpec : public CHeapObj<mtGC> {
friend class VMStructs;
private:
Generation::Name _name;
@@ -71,7 +71,7 @@
// The specification of a permanent generation. This class is very
// similar to GenerationSpec in use. Due to PermGen's not being a
// true Generation, we cannot combine the spec classes either.
-class PermanentGenerationSpec : public CHeapObj {
+class PermanentGenerationSpec : public CHeapObj<mtGC> {
friend class VMStructs;
private:
PermGen::Name _name;
--- a/hotspot/src/share/vm/memory/heap.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/heap.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -26,7 +26,7 @@
#include "memory/heap.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/os.hpp"
-
+#include "services/memTracker.hpp"
size_t CodeHeap::header_size() {
return sizeof(HeapBlock);
@@ -130,6 +130,9 @@
if (!_segmap.initialize(align_to_page_size(_number_of_reserved_segments), align_to_page_size(_number_of_committed_segments))) {
return false;
}
+
+ MemTracker::record_virtual_memory_type((address)_segmap.low_boundary(), mtCode);
+
assert(_segmap.committed_size() >= (size_t) _number_of_committed_segments, "could not commit enough space for segment map");
assert(_segmap.reserved_size() >= (size_t) _number_of_reserved_segments , "could not reserve enough space for segment map");
assert(_segmap.reserved_size() >= _segmap.committed_size() , "just checking");
--- a/hotspot/src/share/vm/memory/heap.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/heap.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -77,7 +77,7 @@
void set_link(FreeBlock* link) { _link = link; }
};
-class CodeHeap : public CHeapObj {
+class CodeHeap : public CHeapObj<mtCode> {
friend class VMStructs;
private:
VirtualSpace _memory; // the memory holding the blocks
--- a/hotspot/src/share/vm/memory/heapInspection.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/heapInspection.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -116,7 +116,7 @@
KlassInfoTable::KlassInfoTable(int size, HeapWord* ref) {
_size = 0;
_ref = ref;
- _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size);
+ _buckets = NEW_C_HEAP_ARRAY(KlassInfoBucket, size, mtInternal);
if (_buckets != NULL) {
_size = size;
for (int index = 0; index < _size; index++) {
@@ -130,7 +130,7 @@
for (int index = 0; index < _size; index++) {
_buckets[index].empty();
}
- FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets);
+ FREE_C_HEAP_ARRAY(KlassInfoBucket, _buckets, mtInternal);
_size = 0;
}
}
@@ -179,7 +179,7 @@
KlassInfoHisto::KlassInfoHisto(const char* title, int estimatedCount) :
_title(title) {
- _elements = new (ResourceObj::C_HEAP) GrowableArray<KlassInfoEntry*>(estimatedCount,true);
+ _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<KlassInfoEntry*>(estimatedCount,true);
}
KlassInfoHisto::~KlassInfoHisto() {
--- a/hotspot/src/share/vm/memory/heapInspection.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/heapInspection.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -44,7 +44,7 @@
// to KlassInfoEntry's and is used to sort
// the entries.
-class KlassInfoEntry: public CHeapObj {
+class KlassInfoEntry: public CHeapObj<mtInternal> {
private:
KlassInfoEntry* _next;
klassOop _klass;
@@ -72,7 +72,7 @@
virtual void do_cinfo(KlassInfoEntry* cie) = 0;
};
-class KlassInfoBucket: public CHeapObj {
+class KlassInfoBucket: public CHeapObj<mtInternal> {
private:
KlassInfoEntry* _list;
KlassInfoEntry* list() { return _list; }
--- a/hotspot/src/share/vm/memory/memRegion.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/memRegion.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -99,8 +99,8 @@
class MemRegionClosureRO: public MemRegionClosure {
public:
- void* operator new(size_t size, ResourceObj::allocation_type type) {
- return ResourceObj::operator new(size, type);
+ void* operator new(size_t size, ResourceObj::allocation_type type, MEMFLAGS flags) {
+ return ResourceObj::operator new(size, type, flags);
}
void* operator new(size_t size, Arena *arena) {
return ResourceObj::operator new(size, arena);
--- a/hotspot/src/share/vm/memory/permGen.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/permGen.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -42,7 +42,7 @@
// PermGen models the part of the heap used to allocate class meta-data.
-class PermGen : public CHeapObj {
+class PermGen : public CHeapObj<mtGC> {
friend class VMStructs;
protected:
size_t _capacity_expansion_limit; // maximum expansion allowed without a
--- a/hotspot/src/share/vm/memory/referencePolicy.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/referencePolicy.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -29,7 +29,7 @@
// should be cleared.
-class ReferencePolicy : public CHeapObj {
+class ReferencePolicy : public CHeapObj<mtGC> {
public:
virtual bool should_clear_reference(oop p, jlong timestamp_clock) {
ShouldNotReachHere();
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -108,7 +108,8 @@
_num_q = MAX2(1U, mt_processing_degree);
_max_num_q = MAX2(_num_q, mt_discovery_degree);
_discovered_refs = NEW_C_HEAP_ARRAY(DiscoveredList,
- _max_num_q * number_of_subclasses_of_ref());
+ _max_num_q * number_of_subclasses_of_ref(), mtGC);
+
if (_discovered_refs == NULL) {
vm_exit_during_initialization("Could not allocated RefProc Array");
}
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -203,7 +203,7 @@
}
};
-class ReferenceProcessor : public CHeapObj {
+class ReferenceProcessor : public CHeapObj<mtGC> {
protected:
// Compatibility with pre-4965777 JDK's
static bool _pending_list_uses_discovered_field;
--- a/hotspot/src/share/vm/memory/resourceArea.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/resourceArea.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
if (UseMallocOnly) {
// use malloc, but save pointer in res. area for later freeing
char** save = (char**)internal_malloc_4(sizeof(char*));
- return (*save = (char*)os::malloc(size));
+ return (*save = (char*)os::malloc(size, mtThread));
}
#endif
return (char*)Amalloc(size);
@@ -93,18 +93,17 @@
ResourceArea *_area; // Resource area to stack allocate
Chunk *_chunk; // saved arena chunk
char *_hwm, *_max;
- NOT_PRODUCT(size_t _size_in_bytes;)
+ size_t _size_in_bytes;
void initialize(Thread *thread) {
_area = thread->resource_area();
_chunk = _area->_chunk;
_hwm = _area->_hwm;
_max= _area->_max;
- NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
+ _size_in_bytes = _area->size_in_bytes();
debug_only(_area->_nesting++;)
assert( _area->_nesting > 0, "must stack allocate RMs" );
}
-
public:
#ifndef ASSERT
@@ -120,7 +119,7 @@
ResourceMark( ResourceArea *r ) :
_area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) {
- NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
+ _size_in_bytes = r->_size_in_bytes;
debug_only(_area->_nesting++;)
assert( _area->_nesting > 0, "must stack allocate RMs" );
}
@@ -148,7 +147,7 @@
private:
void free_malloced_objects() PRODUCT_RETURN;
- size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0;
+ size_t size_in_bytes() { return _size_in_bytes; }
};
//------------------------------DeoptResourceMark-----------------------------------
@@ -180,19 +179,19 @@
// and they would be stack allocated. This leaves open the possibilty of accidental
// misuse so we simple duplicate the ResourceMark functionality here.
-class DeoptResourceMark: public CHeapObj {
+class DeoptResourceMark: public CHeapObj<mtInternal> {
protected:
ResourceArea *_area; // Resource area to stack allocate
Chunk *_chunk; // saved arena chunk
char *_hwm, *_max;
- NOT_PRODUCT(size_t _size_in_bytes;)
+ size_t _size_in_bytes;
void initialize(Thread *thread) {
_area = thread->resource_area();
_chunk = _area->_chunk;
_hwm = _area->_hwm;
_max= _area->_max;
- NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
+ _size_in_bytes = _area->size_in_bytes();
debug_only(_area->_nesting++;)
assert( _area->_nesting > 0, "must stack allocate RMs" );
}
@@ -212,7 +211,7 @@
DeoptResourceMark( ResourceArea *r ) :
_area(r), _chunk(r->_chunk), _hwm(r->_hwm), _max(r->_max) {
- NOT_PRODUCT(_size_in_bytes = _area->size_in_bytes();)
+ _size_in_bytes = _area->size_in_bytes();
debug_only(_area->_nesting++;)
assert( _area->_nesting > 0, "must stack allocate RMs" );
}
@@ -240,7 +239,7 @@
private:
void free_malloced_objects() PRODUCT_RETURN;
- size_t size_in_bytes() NOT_PRODUCT({ return _size_in_bytes; }) PRODUCT_RETURN0;
+ size_t size_in_bytes() { return _size_in_bytes; };
};
#endif // SHARE_VM_MEMORY_RESOURCEAREA_HPP
--- a/hotspot/src/share/vm/memory/restore.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/restore.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -132,7 +132,7 @@
buffer += sizeof(intptr_t);
int number_of_entries = *(intptr_t*)buffer;
buffer += sizeof(intptr_t);
- SymbolTable::create_table((HashtableBucket*)buffer, symbolTableLen,
+ SymbolTable::create_table((HashtableBucket<mtSymbol>*)buffer, symbolTableLen,
number_of_entries);
buffer += symbolTableLen;
@@ -144,7 +144,7 @@
buffer += sizeof(intptr_t);
number_of_entries = *(intptr_t*)buffer;
buffer += sizeof(intptr_t);
- StringTable::create_table((HashtableBucket*)buffer, stringTableLen,
+ StringTable::create_table((HashtableBucket<mtSymbol>*)buffer, stringTableLen,
number_of_entries);
buffer += stringTableLen;
@@ -157,7 +157,7 @@
buffer += sizeof(intptr_t);
number_of_entries = *(intptr_t*)buffer;
buffer += sizeof(intptr_t);
- SystemDictionary::set_shared_dictionary((HashtableBucket*)buffer,
+ SystemDictionary::set_shared_dictionary((HashtableBucket<mtClass>*)buffer,
sharedDictionaryLen,
number_of_entries);
buffer += sharedDictionaryLen;
@@ -171,7 +171,7 @@
buffer += sizeof(intptr_t);
number_of_entries = *(intptr_t*)buffer;
buffer += sizeof(intptr_t);
- ClassLoader::create_package_info_table((HashtableBucket*)buffer, pkgInfoLen,
+ ClassLoader::create_package_info_table((HashtableBucket<mtClass>*)buffer, pkgInfoLen,
number_of_entries);
buffer += pkgInfoLen;
ClassLoader::verify();
--- a/hotspot/src/share/vm/memory/space.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/space.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -105,7 +105,7 @@
// bottom() <= top() <= end()
// top() is inclusive and end() is exclusive.
-class Space: public CHeapObj {
+class Space: public CHeapObj<mtGC> {
friend class VMStructs;
protected:
HeapWord* _bottom;
--- a/hotspot/src/share/vm/memory/tenuredGeneration.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/tenuredGeneration.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -65,7 +65,7 @@
if (UseParNewGC && ParallelGCThreads > 0) {
typedef ParGCAllocBufferWithBOT* ParGCAllocBufferWithBOTPtr;
_alloc_buffers = NEW_C_HEAP_ARRAY(ParGCAllocBufferWithBOTPtr,
- ParallelGCThreads);
+ ParallelGCThreads, mtGC);
if (_alloc_buffers == NULL)
vm_exit_during_initialization("Could not allocate alloc_buffers");
for (uint i = 0; i < ParallelGCThreads; i++) {
--- a/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/threadLocalAllocBuffer.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,7 +36,7 @@
// It is thread-private at any time, but maybe multiplexed over
// time across multiple threads. The park()/unpark() pair is
// used to make it avaiable for such multiplexing.
-class ThreadLocalAllocBuffer: public CHeapObj {
+class ThreadLocalAllocBuffer: public CHeapObj<mtThread> {
friend class VMStructs;
private:
HeapWord* _start; // address of TLAB
@@ -172,7 +172,7 @@
void verify();
};
-class GlobalTLABStats: public CHeapObj {
+class GlobalTLABStats: public CHeapObj<mtThread> {
private:
// Accumulate perfdata in private variables because
--- a/hotspot/src/share/vm/memory/universe.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -764,7 +764,7 @@
FileMapInfo* mapinfo = NULL;
if (UseSharedSpaces) {
- mapinfo = NEW_C_HEAP_OBJ(FileMapInfo);
+ mapinfo = NEW_C_HEAP_OBJ(FileMapInfo, mtInternal);
memset(mapinfo, 0, sizeof(FileMapInfo));
// Open the shared archive file, read and validate the header. If
@@ -1546,7 +1546,7 @@
// This is the first previous version so make some space.
// Start with 2 elements under the assumption that the class
// won't be redefined much.
- _prev_methods = new (ResourceObj::C_HEAP) GrowableArray<jweak>(2, true);
+ _prev_methods = new (ResourceObj::C_HEAP, mtClass) GrowableArray<jweak>(2, true);
}
// RC_TRACE macro has an embedded ResourceMark
--- a/hotspot/src/share/vm/memory/universe.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/memory/universe.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -43,7 +43,7 @@
// Common parts of a methodOop cache. This cache safely interacts with
// the RedefineClasses API.
//
-class CommonMethodOopCache : public CHeapObj {
+class CommonMethodOopCache : public CHeapObj<mtClass> {
// We save the klassOop and the idnum of methodOop in order to get
// the current cached methodOop.
private:
@@ -455,7 +455,7 @@
static int base_vtable_size() { return _base_vtable_size; }
};
-class DeferredObjAllocEvent : public CHeapObj {
+class DeferredObjAllocEvent : public CHeapObj<mtInternal> {
private:
oop _oop;
size_t _bytesize;
--- a/hotspot/src/share/vm/oops/constantPoolOop.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/oops/constantPoolOop.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -764,7 +764,7 @@
unsigned char *bytes);
};
-class SymbolHashMapEntry : public CHeapObj {
+class SymbolHashMapEntry : public CHeapObj<mtSymbol> {
private:
unsigned int _hash; // 32-bit hash for item
SymbolHashMapEntry* _next; // Next element in the linked list for this bucket
@@ -790,7 +790,7 @@
}; // End SymbolHashMapEntry class
-class SymbolHashMapBucket : public CHeapObj {
+class SymbolHashMapBucket : public CHeapObj<mtSymbol> {
private:
SymbolHashMapEntry* _entry;
@@ -803,7 +803,7 @@
}; // End SymbolHashMapBucket class
-class SymbolHashMap: public CHeapObj {
+class SymbolHashMap: public CHeapObj<mtSymbol> {
private:
// Default number of entries in the table
@@ -816,7 +816,7 @@
void initialize_table(int table_size) {
_table_size = table_size;
- _buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size);
+ _buckets = NEW_C_HEAP_ARRAY(SymbolHashMapBucket, table_size, mtSymbol);
for (int index = 0; index < table_size; index++) {
_buckets[index].clear();
}
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -847,7 +847,6 @@
Klass::shared_symbols_iterate(closure);
closure->do_symbol(&_generic_signature);
closure->do_symbol(&_source_file_name);
- closure->do_symbol(&_source_debug_extension);
for (JavaFieldStream fs(this); !fs.done(); fs.next()) {
int name_index = fs.name_index();
@@ -989,7 +988,7 @@
fieldDescriptor fd;
int length = java_fields_count();
// In DebugInfo nonstatic fields are sorted by offset.
- int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1));
+ int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1), mtClass);
int j = 0;
for (int i = 0; i < length; i += 1) {
fd.initialize(as_klassOop(), i);
@@ -1009,7 +1008,7 @@
cl->do_field(&fd);
}
}
- FREE_C_HEAP_ARRAY(int, fields_sorted);
+ FREE_C_HEAP_ARRAY(int, fields_sorted, mtClass);
}
@@ -1236,7 +1235,7 @@
if (length <= idnum) {
// allocate a new cache that might be used
size_t size = MAX2(idnum+1, (size_t)ik_h->idnum_allocated_count());
- new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1);
+ new_jmeths = NEW_C_HEAP_ARRAY(jmethodID, size+1, mtClass);
memset(new_jmeths, 0, (size+1)*sizeof(jmethodID));
// cache size is stored in element[0], other elements offset by one
new_jmeths[0] = (jmethodID)size;
@@ -1397,7 +1396,7 @@
// cache size is stored in element[0], other elements offset by one
if (indices == NULL || (length = (size_t)indices[0]) <= idnum) {
size_t size = MAX2(idnum+1, (size_t)idnum_allocated_count());
- int* new_indices = NEW_C_HEAP_ARRAY(int, size+1);
+ int* new_indices = NEW_C_HEAP_ARRAY(int, size+1, mtClass);
new_indices[0] = (int)size;
// copy any existing entries
size_t i;
@@ -1933,7 +1932,7 @@
// deallocate the cached class file
if (_cached_class_file_bytes != NULL) {
- os::free(_cached_class_file_bytes);
+ os::free(_cached_class_file_bytes, mtClass);
_cached_class_file_bytes = NULL;
_cached_class_file_len = 0;
}
@@ -1944,9 +1943,10 @@
// class can't be referenced anymore).
if (_array_name != NULL) _array_name->decrement_refcount();
if (_source_file_name != NULL) _source_file_name->decrement_refcount();
- if (_source_debug_extension != NULL) _source_debug_extension->decrement_refcount();
// walk constant pool and decrement symbol reference counts
_constants->unreference_symbols();
+
+ if (_source_debug_extension != NULL) FREE_C_HEAP_ARRAY(char, _source_debug_extension, mtClass);
}
void instanceKlass::set_source_file_name(Symbol* n) {
@@ -1954,9 +1954,22 @@
if (_source_file_name != NULL) _source_file_name->increment_refcount();
}
-void instanceKlass::set_source_debug_extension(Symbol* n) {
- _source_debug_extension = n;
- if (_source_debug_extension != NULL) _source_debug_extension->increment_refcount();
+void instanceKlass::set_source_debug_extension(char* array, int length) {
+ if (array == NULL) {
+ _source_debug_extension = NULL;
+ } else {
+ // Adding one to the attribute length in order to store a null terminator
+ // character could cause an overflow because the attribute length is
+ // already coded with an u4 in the classfile, but in practice, it's
+ // unlikely to happen.
+ assert((length+1) > length, "Overflow checking");
+ char* sde = NEW_C_HEAP_ARRAY(char, (length + 1), mtClass);
+ for (int i = 0; i < length; i++) {
+ sde[i] = array[i];
+ }
+ sde[length] = '\0';
+ _source_debug_extension = sde;
+ }
}
address instanceKlass::static_field_addr(int offset) {
@@ -2530,7 +2543,7 @@
// This is the first previous version so make some space.
// Start with 2 elements under the assumption that the class
// won't be redefined much.
- _previous_versions = new (ResourceObj::C_HEAP)
+ _previous_versions = new (ResourceObj::C_HEAP, mtClass)
GrowableArray<PreviousVersionNode *>(2, true);
}
@@ -2556,7 +2569,7 @@
("add: all methods are obsolete; flushing any EMCP weak refs"));
} else {
int local_count = 0;
- GrowableArray<jweak>* method_refs = new (ResourceObj::C_HEAP)
+ GrowableArray<jweak>* method_refs = new (ResourceObj::C_HEAP, mtClass)
GrowableArray<jweak>(emcp_method_count, true);
for (int i = 0; i < old_methods->length(); i++) {
if (emcp_methods->at(i)) {
@@ -2948,7 +2961,7 @@
while (_current_index < length) {
PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
- PreviousVersionInfo * pv_info = new (ResourceObj::C_HEAP)
+ PreviousVersionInfo * pv_info = new (ResourceObj::C_HEAP, mtClass)
PreviousVersionInfo(pv_node);
constantPoolHandle cp_h = pv_info->prev_constant_pool_handle();
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -226,7 +226,9 @@
// Name of source file containing this klass, NULL if not specified.
Symbol* _source_file_name;
// the source debug extension for this klass, NULL if not specified.
- Symbol* _source_debug_extension;
+ // Specified as UTF-8 string without terminating zero byte in the classfile,
+ // it is stored in the instanceklass as a NULL-terminated UTF-8 string
+ char* _source_debug_extension;
// Generic signature, or null if none.
Symbol* _generic_signature;
// Array name derived from this class which needs unreferencing
@@ -542,8 +544,8 @@
void set_major_version(u2 major_version) { _major_version = major_version; }
// source debug extension
- Symbol* source_debug_extension() const { return _source_debug_extension; }
- void set_source_debug_extension(Symbol* n);
+ char* source_debug_extension() const { return _source_debug_extension; }
+ void set_source_debug_extension(char* array, int length);
// symbol unloading support (refcount already added)
Symbol* array_name() { return _array_name; }
@@ -1008,7 +1010,7 @@
/* JNIid class for jfieldIDs only */
-class JNIid: public CHeapObj {
+class JNIid: public CHeapObj<mtClass> {
friend class VMStructs;
private:
klassOop _holder;
@@ -1059,7 +1061,7 @@
// reference must be used because a weak reference would be seen as
// collectible. A GrowableArray of PreviousVersionNodes is attached
// to the instanceKlass as needed. See PreviousVersionWalker below.
-class PreviousVersionNode : public CHeapObj {
+class PreviousVersionNode : public CHeapObj<mtClass> {
private:
// A shared ConstantPool is never collected so we'll always have
// a reference to it so we can update items in the cache. We'll
@@ -1154,7 +1156,7 @@
// noticed since an nmethod should be removed as many times are it's
// added.
//
-class nmethodBucket: public CHeapObj {
+class nmethodBucket: public CHeapObj<mtClass> {
friend class VMStructs;
private:
nmethod* _nmethod;
--- a/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlassKlass.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -421,8 +421,7 @@
ik->set_protection_domain(NULL);
ik->set_signers(NULL);
ik->set_source_file_name(NULL);
- ik->set_source_debug_extension(NULL);
- ik->set_source_debug_extension(NULL);
+ ik->set_source_debug_extension(NULL, 0);
ik->set_array_name(NULL);
ik->set_inner_classes(NULL);
ik->set_static_oop_field_count(0);
@@ -531,7 +530,7 @@
}
if (ik->source_debug_extension() != NULL) {
st->print(BULLET"source debug extension: ");
- ik->source_debug_extension()->print_value_on(st);
+ st->print_cr("%s", ik->source_debug_extension());
st->cr();
}
--- a/hotspot/src/share/vm/oops/methodOop.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/oops/methodOop.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -801,7 +801,7 @@
// breakpoints are written only at safepoints, and are read
// concurrently only outside of safepoints.
-class BreakpointInfo : public CHeapObj {
+class BreakpointInfo : public CHeapObj<mtClass> {
friend class VMStructs;
private:
Bytecodes::Code _orig_bytecode;
--- a/hotspot/src/share/vm/oops/symbol.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/oops/symbol.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -38,7 +38,7 @@
void* Symbol::operator new(size_t sz, int len, TRAPS) {
int alloc_size = object_size(len)*HeapWordSize;
- address res = (address) AllocateHeap(alloc_size, "symbol");
+ address res = (address) AllocateHeap(alloc_size, mtSymbol);
DEBUG_ONLY(set_allocation_type(res, ResourceObj::C_HEAP);)
return res;
}
--- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -130,15 +130,15 @@
} else {
st.print("%s%d", PrintIdealGraphFile, _file_count);
}
- fileStream *stream = new (ResourceObj::C_HEAP) fileStream(st.as_string());
+ fileStream *stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(st.as_string());
_output = stream;
} else {
- fileStream *stream = new (ResourceObj::C_HEAP) fileStream(PrintIdealGraphFile);
+ fileStream *stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(PrintIdealGraphFile);
_output = stream;
}
_file_count++;
} else {
- _stream = new (ResourceObj::C_HEAP) networkStream();
+ _stream = new (ResourceObj::C_HEAP, mtCompiler) networkStream();
// Try to connect to visualizer
if (_stream->connect(PrintIdealGraphAddress, PrintIdealGraphPort)) {
@@ -160,7 +160,7 @@
}
}
- _xml = new (ResourceObj::C_HEAP) xmlStream(_output);
+ _xml = new (ResourceObj::C_HEAP, mtCompiler) xmlStream(_output);
head(TOP_ELEMENT);
}
--- a/hotspot/src/share/vm/opto/library_call.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/library_call.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -160,6 +160,7 @@
bool inline_trans(vmIntrinsics::ID id);
bool inline_abs(vmIntrinsics::ID id);
bool inline_sqrt(vmIntrinsics::ID id);
+ void finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName);
bool inline_pow(vmIntrinsics::ID id);
bool inline_exp(vmIntrinsics::ID id);
bool inline_min_max(vmIntrinsics::ID id);
@@ -1535,40 +1536,79 @@
return true;
}
+void LibraryCallKit::finish_pow_exp(Node* result, Node* x, Node* y, const TypeFunc* call_type, address funcAddr, const char* funcName) {
+ //-------------------
+ //result=(result.isNaN())? funcAddr():result;
+ // Check: If isNaN() by checking result!=result? then either trap
+ // or go to runtime
+ Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result));
+ // Build the boolean node
+ Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) );
+
+ if (!too_many_traps(Deoptimization::Reason_intrinsic)) {
+ {
+ BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT);
+ // End the current control-flow path
+ push_pair(x);
+ if (y != NULL) {
+ push_pair(y);
+ }
+ // The pow or exp intrinsic returned a NaN, which requires a call
+ // to the runtime. Recompile with the runtime call.
+ uncommon_trap(Deoptimization::Reason_intrinsic,
+ Deoptimization::Action_make_not_entrant);
+ }
+ push_pair(result);
+ } else {
+ // If this inlining ever returned NaN in the past, we compile a call
+ // to the runtime to properly handle corner cases
+
+ IfNode* iff = create_and_xform_if(control(), bolisnum, PROB_STATIC_FREQUENT, COUNT_UNKNOWN);
+ Node* if_slow = _gvn.transform( new (C, 1) IfFalseNode(iff) );
+ Node* if_fast = _gvn.transform( new (C, 1) IfTrueNode(iff) );
+
+ if (!if_slow->is_top()) {
+ RegionNode* result_region = new(C, 3) RegionNode(3);
+ PhiNode* result_val = new (C, 3) PhiNode(result_region, Type::DOUBLE);
+
+ result_region->init_req(1, if_fast);
+ result_val->init_req(1, result);
+
+ set_control(if_slow);
+
+ const TypePtr* no_memory_effects = NULL;
+ Node* rt = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName,
+ no_memory_effects,
+ x, top(), y, y ? top() : NULL);
+ Node* value = _gvn.transform(new (C, 1) ProjNode(rt, TypeFunc::Parms+0));
+#ifdef ASSERT
+ Node* value_top = _gvn.transform(new (C, 1) ProjNode(rt, TypeFunc::Parms+1));
+ assert(value_top == top(), "second value must be top");
+#endif
+
+ result_region->init_req(2, control());
+ result_val->init_req(2, value);
+ push_result(result_region, result_val);
+ } else {
+ push_pair(result);
+ }
+ }
+}
+
//------------------------------inline_exp-------------------------------------
// Inline exp instructions, if possible. The Intel hardware only misses
// really odd corner cases (+/- Infinity). Just uncommon-trap them.
bool LibraryCallKit::inline_exp(vmIntrinsics::ID id) {
assert(id == vmIntrinsics::_dexp, "Not exp");
- // If this inlining ever returned NaN in the past, we do not intrinsify it
- // every again. NaN results requires StrictMath.exp handling.
- if (too_many_traps(Deoptimization::Reason_intrinsic)) return false;
-
_sp += arg_size(); // restore stack pointer
Node *x = pop_math_arg();
Node *result = _gvn.transform(new (C, 2) ExpDNode(0,x));
- //-------------------
- //result=(result.isNaN())? StrictMath::exp():result;
- // Check: If isNaN() by checking result!=result? then go to Strict Math
- Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result));
- // Build the boolean node
- Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) );
-
- { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT);
- // End the current control-flow path
- push_pair(x);
- // Math.exp intrinsic returned a NaN, which requires StrictMath.exp
- // to handle. Recompile without intrinsifying Math.exp
- uncommon_trap(Deoptimization::Reason_intrinsic,
- Deoptimization::Action_make_not_entrant);
- }
+ finish_pow_exp(result, x, NULL, OptoRuntime::Math_D_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dexp), "EXP");
C->set_has_split_ifs(true); // Has chance for split-if optimization
- push_pair(result);
-
return true;
}
@@ -1577,17 +1617,12 @@
bool LibraryCallKit::inline_pow(vmIntrinsics::ID id) {
assert(id == vmIntrinsics::_dpow, "Not pow");
- // If this inlining ever returned NaN in the past, we do not intrinsify it
- // every again. NaN results requires StrictMath.pow handling.
- if (too_many_traps(Deoptimization::Reason_intrinsic)) return false;
-
- // Do not intrinsify on older platforms which lack cmove.
- if (ConditionalMoveLimit == 0) return false;
-
// Pseudocode for pow
// if (x <= 0.0) {
- // if ((double)((int)y)==y) { // if y is int
- // result = ((1&(int)y)==0)?-DPow(abs(x), y):DPow(abs(x), y)
+ // long longy = (long)y;
+ // if ((double)longy == y) { // if y is long
+ // if (y + 1 == y) longy = 0; // huge number: even
+ // result = ((1&longy) == 0)?-DPow(abs(x), y):DPow(abs(x), y);
// } else {
// result = NaN;
// }
@@ -1595,7 +1630,7 @@
// result = DPow(x,y);
// }
// if (result != result)? {
- // uncommon_trap();
+ // result = uncommon_trap() or runtime_call();
// }
// return result;
@@ -1603,15 +1638,14 @@
Node* y = pop_math_arg();
Node* x = pop_math_arg();
- Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, x, y) );
-
- // Short form: if not top-level (i.e., Math.pow but inlining Math.pow
- // inside of something) then skip the fancy tests and just check for
- // NaN result.
- Node *result = NULL;
- if( jvms()->depth() >= 1 ) {
- result = fast_result;
+ Node* result = NULL;
+
+ if (!too_many_traps(Deoptimization::Reason_intrinsic)) {
+ // Short form: skip the fancy tests and just check for NaN result.
+ result = _gvn.transform( new (C, 3) PowDNode(0, x, y) );
} else {
+ // If this inlining ever returned NaN in the past, include all
+ // checks + call to the runtime.
// Set the merge point for If node with condition of (x <= 0.0)
// There are four possible paths to region node and phi node
@@ -1627,55 +1661,95 @@
Node *bol1 = _gvn.transform( new (C, 2) BoolNode( cmp, BoolTest::le ) );
// Branch either way
IfNode *if1 = create_and_xform_if(control(),bol1, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN);
- Node *opt_test = _gvn.transform(if1);
- //assert( opt_test->is_If(), "Expect an IfNode");
- IfNode *opt_if1 = (IfNode*)opt_test;
// Fast path taken; set region slot 3
- Node *fast_taken = _gvn.transform( new (C, 1) IfFalseNode(opt_if1) );
+ Node *fast_taken = _gvn.transform( new (C, 1) IfFalseNode(if1) );
r->init_req(3,fast_taken); // Capture fast-control
// Fast path not-taken, i.e. slow path
- Node *complex_path = _gvn.transform( new (C, 1) IfTrueNode(opt_if1) );
+ Node *complex_path = _gvn.transform( new (C, 1) IfTrueNode(if1) );
// Set fast path result
- Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, y, x) );
+ Node *fast_result = _gvn.transform( new (C, 3) PowDNode(0, x, y) );
phi->init_req(3, fast_result);
// Complex path
- // Build the second if node (if y is int)
- // Node for (int)y
- Node *inty = _gvn.transform( new (C, 2) ConvD2INode(y));
- // Node for (double)((int) y)
- Node *doubleinty= _gvn.transform( new (C, 2) ConvI2DNode(inty));
- // Check (double)((int) y) : y
- Node *cmpinty= _gvn.transform(new (C, 3) CmpDNode(doubleinty, y));
- // Check if (y isn't int) then go to slow path
-
- Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmpinty, BoolTest::ne ) );
+ // Build the second if node (if y is long)
+ // Node for (long)y
+ Node *longy = _gvn.transform( new (C, 2) ConvD2LNode(y));
+ // Node for (double)((long) y)
+ Node *doublelongy= _gvn.transform( new (C, 2) ConvL2DNode(longy));
+ // Check (double)((long) y) : y
+ Node *cmplongy= _gvn.transform(new (C, 3) CmpDNode(doublelongy, y));
+ // Check if (y isn't long) then go to slow path
+
+ Node *bol2 = _gvn.transform( new (C, 2) BoolNode( cmplongy, BoolTest::ne ) );
// Branch either way
IfNode *if2 = create_and_xform_if(complex_path,bol2, PROB_STATIC_INFREQUENT, COUNT_UNKNOWN);
- Node *slow_path = opt_iff(r,if2); // Set region path 2
-
- // Calculate DPow(abs(x), y)*(1 & (int)y)
+ Node* ylong_path = _gvn.transform( new (C, 1) IfFalseNode(if2));
+
+ Node *slow_path = _gvn.transform( new (C, 1) IfTrueNode(if2) );
+
+ // Calculate DPow(abs(x), y)*(1 & (long)y)
// Node for constant 1
- Node *conone = intcon(1);
- // 1& (int)y
- Node *signnode= _gvn.transform( new (C, 3) AndINode(conone, inty) );
+ Node *conone = longcon(1);
+ // 1& (long)y
+ Node *signnode= _gvn.transform( new (C, 3) AndLNode(conone, longy) );
+
+ // A huge number is always even. Detect a huge number by checking
+ // if y + 1 == y and set integer to be tested for parity to 0.
+ // Required for corner case:
+ // (long)9.223372036854776E18 = max_jlong
+ // (double)(long)9.223372036854776E18 = 9.223372036854776E18
+ // max_jlong is odd but 9.223372036854776E18 is even
+ Node* yplus1 = _gvn.transform( new (C, 3) AddDNode(y, makecon(TypeD::make(1))));
+ Node *cmpyplus1= _gvn.transform(new (C, 3) CmpDNode(yplus1, y));
+ Node *bolyplus1 = _gvn.transform( new (C, 2) BoolNode( cmpyplus1, BoolTest::eq ) );
+ Node* correctedsign = NULL;
+ if (ConditionalMoveLimit != 0) {
+ correctedsign = _gvn.transform( CMoveNode::make(C, NULL, bolyplus1, signnode, longcon(0), TypeLong::LONG));
+ } else {
+ IfNode *ifyplus1 = create_and_xform_if(ylong_path,bolyplus1, PROB_FAIR, COUNT_UNKNOWN);
+ RegionNode *r = new (C, 3) RegionNode(3);
+ Node *phi = new (C, 3) PhiNode(r, TypeLong::LONG);
+ r->init_req(1, _gvn.transform( new (C, 1) IfFalseNode(ifyplus1)));
+ r->init_req(2, _gvn.transform( new (C, 1) IfTrueNode(ifyplus1)));
+ phi->init_req(1, signnode);
+ phi->init_req(2, longcon(0));
+ correctedsign = _gvn.transform(phi);
+ ylong_path = _gvn.transform(r);
+ record_for_igvn(r);
+ }
+
// zero node
- Node *conzero = intcon(0);
- // Check (1&(int)y)==0?
- Node *cmpeq1 = _gvn.transform(new (C, 3) CmpINode(signnode, conzero));
- // Check if (1&(int)y)!=0?, if so the result is negative
+ Node *conzero = longcon(0);
+ // Check (1&(long)y)==0?
+ Node *cmpeq1 = _gvn.transform(new (C, 3) CmpLNode(correctedsign, conzero));
+ // Check if (1&(long)y)!=0?, if so the result is negative
Node *bol3 = _gvn.transform( new (C, 2) BoolNode( cmpeq1, BoolTest::ne ) );
// abs(x)
Node *absx=_gvn.transform( new (C, 2) AbsDNode(x));
// abs(x)^y
- Node *absxpowy = _gvn.transform( new (C, 3) PowDNode(0, y, absx) );
+ Node *absxpowy = _gvn.transform( new (C, 3) PowDNode(0, absx, y) );
// -abs(x)^y
Node *negabsxpowy = _gvn.transform(new (C, 2) NegDNode (absxpowy));
- // (1&(int)y)==1?-DPow(abs(x), y):DPow(abs(x), y)
- Node *signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE));
+ // (1&(long)y)==1?-DPow(abs(x), y):DPow(abs(x), y)
+ Node *signresult = NULL;
+ if (ConditionalMoveLimit != 0) {
+ signresult = _gvn.transform( CMoveNode::make(C, NULL, bol3, absxpowy, negabsxpowy, Type::DOUBLE));
+ } else {
+ IfNode *ifyeven = create_and_xform_if(ylong_path,bol3, PROB_FAIR, COUNT_UNKNOWN);
+ RegionNode *r = new (C, 3) RegionNode(3);
+ Node *phi = new (C, 3) PhiNode(r, Type::DOUBLE);
+ r->init_req(1, _gvn.transform( new (C, 1) IfFalseNode(ifyeven)));
+ r->init_req(2, _gvn.transform( new (C, 1) IfTrueNode(ifyeven)));
+ phi->init_req(1, absxpowy);
+ phi->init_req(2, negabsxpowy);
+ signresult = _gvn.transform(phi);
+ ylong_path = _gvn.transform(r);
+ record_for_igvn(r);
+ }
// Set complex path fast result
+ r->init_req(2, ylong_path);
phi->init_req(2, signresult);
static const jlong nan_bits = CONST64(0x7ff8000000000000);
@@ -1689,27 +1763,10 @@
result=_gvn.transform(phi);
}
- //-------------------
- //result=(result.isNaN())? uncommon_trap():result;
- // Check: If isNaN() by checking result!=result? then go to Strict Math
- Node* cmpisnan = _gvn.transform(new (C, 3) CmpDNode(result,result));
- // Build the boolean node
- Node* bolisnum = _gvn.transform( new (C, 2) BoolNode(cmpisnan, BoolTest::eq) );
-
- { BuildCutout unless(this, bolisnum, PROB_STATIC_FREQUENT);
- // End the current control-flow path
- push_pair(x);
- push_pair(y);
- // Math.pow intrinsic returned a NaN, which requires StrictMath.pow
- // to handle. Recompile without intrinsifying Math.pow.
- uncommon_trap(Deoptimization::Reason_intrinsic,
- Deoptimization::Action_make_not_entrant);
- }
+ finish_pow_exp(result, x, y, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW");
C->set_has_split_ifs(true); // Has chance for split-if optimization
- push_pair(result);
-
return true;
}
--- a/hotspot/src/share/vm/opto/macro.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/macro.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -409,7 +409,7 @@
Node *alloc_mem = alloc->in(TypeFunc::Memory);
uint length = mem->req();
- GrowableArray <Node *> values(length, length, NULL);
+ GrowableArray <Node *> values(length, length, NULL, false);
// create a new Phi for the value
PhiNode *phi = new (C, length) PhiNode(mem->in(0), phi_type, NULL, instance_id, alias_idx, offset);
--- a/hotspot/src/share/vm/opto/parse2.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/parse2.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1278,9 +1278,9 @@
// or the narrowOop equivalent.
const Type* obj_type = _gvn.type(obj);
const TypeOopPtr* tboth = obj_type->join(con_type)->isa_oopptr();
- if (tboth != NULL && tboth != obj_type && tboth->higher_equal(obj_type)) {
+ if (tboth != NULL && tboth->klass_is_exact() && tboth != obj_type &&
+ tboth->higher_equal(obj_type)) {
// obj has to be of the exact type Foo if the CmpP succeeds.
- assert(tboth->klass_is_exact(), "klass should be exact");
int obj_in_map = map()->find_edge(obj);
JVMState* jvms = this->jvms();
if (obj_in_map >= 0 &&
--- a/hotspot/src/share/vm/opto/runtime.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/runtime.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -55,7 +55,7 @@
// code in various ways. Currently they are used by the lock coarsening code
//
-class NamedCounter : public CHeapObj {
+class NamedCounter : public CHeapObj<mtCompiler> {
public:
enum CounterTag {
NoTag,
--- a/hotspot/src/share/vm/opto/subnode.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/subnode.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -554,9 +554,7 @@
return TypeInt::CC_GE;
} else if (hi0 <= lo1) {
// Check for special case in Hashtable::get. (See below.)
- if ((jint)lo0 >= 0 && (jint)lo1 >= 0 &&
- in(1)->Opcode() == Op_ModI &&
- in(1)->in(2) == in(2) )
+ if ((jint)lo0 >= 0 && (jint)lo1 >= 0 && is_index_range_check())
return TypeInt::CC_LT;
return TypeInt::CC_LE;
}
@@ -567,13 +565,17 @@
// to be positive.
// (This is a gross hack, since the sub method never
// looks at the structure of the node in any other case.)
- if ((jint)lo0 >= 0 && (jint)lo1 >= 0 &&
- in(1)->Opcode() == Op_ModI &&
- in(1)->in(2)->uncast() == in(2)->uncast())
+ if ((jint)lo0 >= 0 && (jint)lo1 >= 0 && is_index_range_check())
return TypeInt::CC_LT;
return TypeInt::CC; // else use worst case results
}
+bool CmpUNode::is_index_range_check() const {
+ // Check for the "(X ModI Y) CmpU Y" shape
+ return (in(1)->Opcode() == Op_ModI &&
+ in(1)->in(2)->eqv_uncast(in(2)));
+}
+
//------------------------------Idealize---------------------------------------
Node *CmpINode::Ideal( PhaseGVN *phase, bool can_reshape ) {
if (phase->type(in(2))->higher_equal(TypeInt::ZERO)) {
--- a/hotspot/src/share/vm/opto/subnode.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/subnode.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -158,6 +158,7 @@
CmpUNode( Node *in1, Node *in2 ) : CmpNode(in1,in2) {}
virtual int Opcode() const;
virtual const Type *sub( const Type *, const Type * ) const;
+ bool is_index_range_check() const;
};
//------------------------------CmpPNode---------------------------------------
--- a/hotspot/src/share/vm/opto/type.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -212,7 +212,7 @@
// locking.
Arena* save = current->type_arena();
- Arena* shared_type_arena = new Arena();
+ Arena* shared_type_arena = new (mtCompiler)Arena();
current->set_type_arena(shared_type_arena);
_shared_type_dict =
--- a/hotspot/src/share/vm/prims/jni.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jni.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,6 +33,7 @@
#ifndef SERIALGC
#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
#endif // SERIALGC
+#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/gcLocker.inline.hpp"
#include "memory/oopFactory.hpp"
@@ -3270,7 +3271,7 @@
int s_len = java_lang_String::length(s);
typeArrayOop s_value = java_lang_String::value(s);
int s_offset = java_lang_String::offset(s);
- jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len + 1); // add one for zero termination
+ jchar* buf = NEW_C_HEAP_ARRAY(jchar, s_len + 1, mtInternal); // add one for zero termination
if (s_len > 0) {
memcpy(buf, s_value->char_at_addr(s_offset), sizeof(jchar)*s_len);
}
@@ -3363,7 +3364,7 @@
#endif /* USDT2 */
oop java_string = JNIHandles::resolve_non_null(string);
size_t length = java_lang_String::utf8_length(java_string);
- char* result = AllocateHeap(length + 1, "GetStringUTFChars");
+ char* result = AllocateHeap(length + 1, mtInternal);
java_lang_String::as_utf8_string(java_string, result, (int) length + 1);
if (isCopy != NULL) *isCopy = JNI_TRUE;
#ifndef USDT2
@@ -3619,7 +3620,7 @@
* Avoid asserts in typeArrayOop. */ \
result = (ElementType*)get_bad_address(); \
} else { \
- result = NEW_C_HEAP_ARRAY(ElementType, len); \
+ result = NEW_C_HEAP_ARRAY(ElementType, len, mtInternal); \
/* copy the array to the c chunk */ \
memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
} \
@@ -3656,7 +3657,7 @@
* Avoid asserts in typeArrayOop. */ \
result = (ElementType*)get_bad_address(); \
} else { \
- result = NEW_C_HEAP_ARRAY(ElementType, len); \
+ result = NEW_C_HEAP_ARRAY(ElementType, len, mtInternal); \
/* copy the array to the c chunk */ \
memcpy(result, a->Tag##_at_addr(0), sizeof(ElementType)*len); \
} \
--- a/hotspot/src/share/vm/prims/jniCheck.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1308,7 +1308,7 @@
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
- jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), "checked_jni_GetStringChars");
+ jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
*tagLocation = STRING_TAG;
jchar* newResult = (jchar*) (tagLocation + 1);
memcpy(newResult, result, len * sizeof(jchar));
@@ -1378,13 +1378,13 @@
assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
size_t len = strlen(result) + 1; // + 1 for NULL termination
- jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), "checked_jni_GetStringUTFChars");
+ jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
*tagLocation = STRING_UTF_TAG;
char* newResult = (char*) (tagLocation + 1);
strcpy(newResult, result);
// Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
// Note that the dtrace arguments for the allocated memory will not match up with this solution.
- FreeHeap((char*)result);
+ FreeHeap((char*)result, mtInternal);
functionExit(env);
return newResult;
--- a/hotspot/src/share/vm/prims/jvm.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvm.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -345,9 +345,13 @@
// Do this after setting user properties to prevent people
// from setting the value with a -D option, as requested.
{
- char as_chars[256];
- jio_snprintf(as_chars, sizeof(as_chars), INTX_FORMAT, MaxDirectMemorySize);
- PUTPROP(props, "sun.nio.MaxDirectMemorySize", as_chars);
+ if (FLAG_IS_DEFAULT(MaxDirectMemorySize)) {
+ PUTPROP(props, "sun.nio.MaxDirectMemorySize", "-1");
+ } else {
+ char as_chars[256];
+ jio_snprintf(as_chars, sizeof(as_chars), UINTX_FORMAT, MaxDirectMemorySize);
+ PUTPROP(props, "sun.nio.MaxDirectMemorySize", as_chars);
+ }
}
// JVM monitoring and management support
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -268,14 +268,18 @@
// JSR45| SourceDebugExtension_attribute {
// JSR45| u2 attribute_name_index;
// JSR45| u4 attribute_length;
-// JSR45| u2 sourcefile_index;
+// JSR45| u1 debug_extension[attribute_length];
// JSR45| }
void JvmtiClassFileReconstituter::write_source_debug_extension_attribute() {
assert(ikh()->source_debug_extension() != NULL, "caller must check");
write_attribute_name_index("SourceDebugExtension");
- write_u4(2); // always length 2
- write_u2(symbol_to_cpool_index(ikh()->source_debug_extension()));
+ int len = (int)strlen(ikh()->source_debug_extension());
+ write_u4(len);
+ u1* ext = (u1*)ikh()->source_debug_extension();
+ for (int i=0; i<len; i++) {
+ write_u1(ext[i]);
+ }
}
// Write (generic) Signature attribute
--- a/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiClassFileReconstituter.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -68,11 +68,11 @@
~JvmtiConstantPoolReconstituter() {
if (_symmap != NULL) {
- os::free(_symmap);
+ os::free(_symmap, mtClass);
_symmap = NULL;
}
if (_classmap != NULL) {
- os::free(_classmap);
+ os::free(_classmap, mtClass);
_classmap = NULL;
}
}
--- a/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiCodeBlobEvents.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -157,7 +157,7 @@
assert(_global_code_blobs == NULL, "checking");
// create the global list
- _global_code_blobs = new (ResourceObj::C_HEAP) GrowableArray<JvmtiCodeBlobDesc*>(50,true);
+ _global_code_blobs = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiCodeBlobDesc*>(50,true);
// iterate over the stub code descriptors and put them in the list first.
int index = 0;
@@ -247,7 +247,7 @@
int pcds_in_method;
pcds_in_method = (nm->scopes_pcs_end() - nm->scopes_pcs_begin());
- map = NEW_C_HEAP_ARRAY(jvmtiAddrLocationMap, pcds_in_method);
+ map = NEW_C_HEAP_ARRAY(jvmtiAddrLocationMap, pcds_in_method, mtInternal);
address scopes_data = nm->scopes_data_begin();
for( pcd = nm->scopes_pcs_begin(); pcd < nm->scopes_pcs_end(); ++pcd ) {
--- a/hotspot/src/share/vm/prims/jvmtiEnv.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnv.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -1012,7 +1012,7 @@
// growable array of jvmti monitors info on the C-heap
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
- new (ResourceObj::C_HEAP) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
+ new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
uint32_t debug_bits = 0;
if (is_thread_fully_suspended(java_thread, true, &debug_bits)) {
@@ -1057,7 +1057,7 @@
// growable array of jvmti monitors info on the C-heap
GrowableArray<jvmtiMonitorStackDepthInfo*> *owned_monitors_list =
- new (ResourceObj::C_HEAP) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
+ new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiMonitorStackDepthInfo*>(1, true);
uint32_t debug_bits = 0;
if (is_thread_fully_suspended(java_thread, true, &debug_bits)) {
@@ -2541,15 +2541,12 @@
if (!Klass::cast(k)->oop_is_instance()) {
return JVMTI_ERROR_ABSENT_INFORMATION;
}
- Symbol* sdeOop = instanceKlass::cast(k)->source_debug_extension();
- NULL_CHECK(sdeOop, JVMTI_ERROR_ABSENT_INFORMATION);
+ char* sde = instanceKlass::cast(k)->source_debug_extension();
+ NULL_CHECK(sde, JVMTI_ERROR_ABSENT_INFORMATION);
{
- JavaThread* current_thread = JavaThread::current();
- ResourceMark rm(current_thread);
- const char* sdecp = (const char*) sdeOop->as_C_string();
- *source_debug_extension_ptr = (char *) jvmtiMalloc(strlen(sdecp)+1);
- strcpy(*source_debug_extension_ptr, sdecp);
+ *source_debug_extension_ptr = (char *) jvmtiMalloc(strlen(sde)+1);
+ strcpy(*source_debug_extension_ptr, sde);
}
}
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -381,7 +381,7 @@
_native_method_prefixes = NULL;
} else {
// there are prefixes, allocate an array to hold them, and fill it
- char** new_prefixes = (char**)os::malloc((prefix_count) * sizeof(char*));
+ char** new_prefixes = (char**)os::malloc((prefix_count) * sizeof(char*), mtInternal);
if (new_prefixes == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
@@ -1150,7 +1150,7 @@
ResourceTracker::ResourceTracker(JvmtiEnv* env) {
_env = env;
- _allocations = new (ResourceObj::C_HEAP) GrowableArray<unsigned char*>(20, true);
+ _allocations = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<unsigned char*>(20, true);
_failed = false;
}
ResourceTracker::~ResourceTracker() {
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -52,7 +52,7 @@
// done via JNI GetEnv() call. Multiple attachments are
// allowed in jvmti.
-class JvmtiEnvBase : public CHeapObj {
+class JvmtiEnvBase : public CHeapObj<mtInternal> {
private:
@@ -175,7 +175,7 @@
if (size == 0) {
*mem_ptr = NULL;
} else {
- *mem_ptr = (unsigned char *)os::malloc((size_t)size);
+ *mem_ptr = (unsigned char *)os::malloc((size_t)size, mtInternal);
if (*mem_ptr == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
@@ -185,7 +185,7 @@
jvmtiError deallocate(unsigned char* mem) {
if (mem != NULL) {
- os::free(mem);
+ os::free(mem, mtInternal);
}
return JVMTI_ERROR_NONE;
}
--- a/hotspot/src/share/vm/prims/jvmtiEnvThreadState.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvThreadState.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -95,7 +95,7 @@
//
JvmtiFramePops::JvmtiFramePops() {
- _pops = new (ResourceObj::C_HEAP) GrowableArray<int> (2, true);
+ _pops = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<int> (2, true);
}
JvmtiFramePops::~JvmtiFramePops() {
--- a/hotspot/src/share/vm/prims/jvmtiEnvThreadState.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiEnvThreadState.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -76,7 +76,7 @@
// It records what frames on a threads stack should post frame_pop events when they're exited.
//
-class JvmtiFramePops : public CHeapObj {
+class JvmtiFramePops : public CHeapObj<mtInternal> {
private:
GrowableArray<int>* _pops;
@@ -107,7 +107,7 @@
// 3: Location of last executed instruction, used to filter out duplicate
// events due to instruction rewriting.
-class JvmtiEnvThreadState : public CHeapObj {
+class JvmtiEnvThreadState : public CHeapObj<mtInternal> {
private:
friend class JvmtiEnv;
JavaThread *_thread;
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -617,7 +617,7 @@
if (caching_needed && *_cached_data_ptr == NULL) {
// data has been changed by the new retransformable agent
// and it hasn't already been cached, cache it
- *_cached_data_ptr = (unsigned char *)os::malloc(_curr_len);
+ *_cached_data_ptr = (unsigned char *)os::malloc(_curr_len, mtInternal);
memcpy(*_cached_data_ptr, _curr_data, _curr_len);
*_cached_length_ptr = _curr_len;
}
@@ -720,7 +720,7 @@
JvmtiCodeBlobEvents::build_jvmti_addr_location_map(nm, &_map, &_map_length);
}
~JvmtiCompiledMethodLoadEventMark() {
- FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, _map);
+ FREE_C_HEAP_ARRAY(jvmtiAddrLocationMap, _map, mtInternal);
}
jint code_size() { return _code_size; }
@@ -2323,7 +2323,7 @@
// register a stub
void JvmtiDynamicCodeEventCollector::register_stub(const char* name, address start, address end) {
if (_code_blobs == NULL) {
- _code_blobs = new (ResourceObj::C_HEAP) GrowableArray<JvmtiCodeBlobDesc*>(1,true);
+ _code_blobs = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiCodeBlobDesc*>(1,true);
}
_code_blobs->append(new JvmtiCodeBlobDesc(name, start, end));
}
@@ -2357,7 +2357,7 @@
void JvmtiVMObjectAllocEventCollector::record_allocation(oop obj) {
assert(is_enabled(), "VM object alloc event collector is not enabled");
if (_allocated == NULL) {
- _allocated = new (ResourceObj::C_HEAP) GrowableArray<oop>(1, true);
+ _allocated = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(1, true);
}
_allocated->push(obj);
}
--- a/hotspot/src/share/vm/prims/jvmtiExport.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -350,7 +350,7 @@
// Support class used by JvmtiDynamicCodeEventCollector and others. It
// describes a single code blob by name and address range.
-class JvmtiCodeBlobDesc : public CHeapObj {
+class JvmtiCodeBlobDesc : public CHeapObj<mtInternal> {
private:
char _name[64];
address _code_begin;
--- a/hotspot/src/share/vm/prims/jvmtiExtensions.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiExtensions.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -49,8 +49,8 @@
// event. The function and the event are registered here.
//
void JvmtiExtensions::register_extensions() {
- _ext_functions = new (ResourceObj::C_HEAP) GrowableArray<jvmtiExtensionFunctionInfo*>(1,true);
- _ext_events = new (ResourceObj::C_HEAP) GrowableArray<jvmtiExtensionEventInfo*>(1,true);
+ _ext_functions = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiExtensionFunctionInfo*>(1,true);
+ _ext_events = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jvmtiExtensionEventInfo*>(1,true);
// register our extension function
static jvmtiParamInfo func_params[] = {
--- a/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiGetLoadedClasses.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -152,7 +152,7 @@
// Public methods that get called within the scope of the closure
void allocate() {
- _list = NEW_C_HEAP_ARRAY(Handle, _count);
+ _list = NEW_C_HEAP_ARRAY(Handle, _count, mtInternal);
assert(_list != NULL, "Out of memory");
if (_list == NULL) {
_count = 0;
--- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -98,8 +98,8 @@
void GrowableCache::recache() {
int len = _elements->length();
- FREE_C_HEAP_ARRAY(address, _cache);
- _cache = NEW_C_HEAP_ARRAY(address,len+1);
+ FREE_C_HEAP_ARRAY(address, _cache, mtInternal);
+ _cache = NEW_C_HEAP_ARRAY(address,len+1, mtInternal);
for (int i=0; i<len; i++) {
_cache[i] = _elements->at(i)->getCacheValue();
@@ -142,13 +142,13 @@
GrowableCache::~GrowableCache() {
clear();
delete _elements;
- FREE_C_HEAP_ARRAY(address, _cache);
+ FREE_C_HEAP_ARRAY(address, _cache, mtInternal);
}
void GrowableCache::initialize(void *this_obj, void listener_fun(void *, address*) ) {
_this_obj = this_obj;
_listener_fun = listener_fun;
- _elements = new (ResourceObj::C_HEAP) GrowableArray<GrowableElement*>(5,true);
+ _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<GrowableElement*>(5,true);
recache();
}
--- a/hotspot/src/share/vm/prims/jvmtiImpl.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiImpl.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -64,7 +64,7 @@
// to update its pointer to the address cache.
//
-class GrowableElement : public CHeapObj {
+class GrowableElement : public CHeapObj<mtInternal> {
public:
virtual address getCacheValue() =0;
virtual bool equals(GrowableElement* e) =0;
@@ -130,7 +130,7 @@
// Note : typesafe wrapper for GrowableCache of JvmtiBreakpoint
//
-class JvmtiBreakpointCache : public CHeapObj {
+class JvmtiBreakpointCache : public CHeapObj<mtInternal> {
private:
GrowableCache _cache;
@@ -258,7 +258,7 @@
// CHeap allocated to emphasize its similarity to JvmtiFramePops.
//
-class JvmtiBreakpoints : public CHeapObj {
+class JvmtiBreakpoints : public CHeapObj<mtInternal> {
private:
JvmtiBreakpointCache _bps;
@@ -496,7 +496,7 @@
class JvmtiDeferredEventQueue : AllStatic {
friend class JvmtiDeferredEvent;
private:
- class QueueNode : public CHeapObj {
+ class QueueNode : public CHeapObj<mtInternal> {
private:
JvmtiDeferredEvent _event;
QueueNode* _next;
--- a/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -27,7 +27,7 @@
#include "runtime/interfaceSupport.hpp"
#include "runtime/thread.hpp"
-GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP) GrowableArray<JvmtiRawMonitor*>(1,true);
+GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1,true);
void JvmtiPendingMonitors::transition_raw_monitors() {
assert((Threads::number_of_threads()==1),
@@ -53,7 +53,7 @@
JvmtiRawMonitor::JvmtiRawMonitor(const char *name) {
#ifdef ASSERT
- _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1), name);
+ _name = strcpy(NEW_C_HEAP_ARRAY(char, strlen(name) + 1, mtInternal), name);
#else
_name = NULL;
#endif
--- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -831,7 +831,7 @@
jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) {
// For consistency allocate memory using os::malloc wrapper.
_scratch_classes = (instanceKlassHandle *)
- os::malloc(sizeof(instanceKlassHandle) * _class_count);
+ os::malloc(sizeof(instanceKlassHandle) * _class_count, mtInternal);
if (_scratch_classes == NULL) {
return JVMTI_ERROR_OUT_OF_MEMORY;
}
@@ -3236,7 +3236,9 @@
// Copy the "source debug extension" attribute from new class version
the_class->set_source_debug_extension(
- scratch_class->source_debug_extension());
+ scratch_class->source_debug_extension(),
+ scratch_class->source_debug_extension() == NULL ? 0 :
+ (int)strlen(scratch_class->source_debug_extension()));
// Use of javac -g could be different in the old and the new
if (scratch_class->access_flags().has_localvariable_table() !=
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -55,7 +55,7 @@
// and the tag value. In addition an entry includes a next pointer which
// is used to chain entries together.
-class JvmtiTagHashmapEntry : public CHeapObj {
+class JvmtiTagHashmapEntry : public CHeapObj<mtInternal> {
private:
friend class JvmtiTagMap;
@@ -106,7 +106,7 @@
// entries. It also provides a function to iterate over all entries
// in the hashmap.
-class JvmtiTagHashmap : public CHeapObj {
+class JvmtiTagHashmap : public CHeapObj<mtInternal> {
private:
friend class JvmtiTagMap;
@@ -150,7 +150,7 @@
_resize_threshold = (int)(_load_factor * _size);
_resizing_enabled = true;
size_t s = initial_size * sizeof(JvmtiTagHashmapEntry*);
- _table = (JvmtiTagHashmapEntry**)os::malloc(s);
+ _table = (JvmtiTagHashmapEntry**)os::malloc(s, mtInternal);
if (_table == NULL) {
vm_exit_out_of_memory(s, "unable to allocate initial hashtable for jvmti object tags");
}
@@ -188,7 +188,7 @@
// allocate new table
size_t s = new_size * sizeof(JvmtiTagHashmapEntry*);
- JvmtiTagHashmapEntry** new_table = (JvmtiTagHashmapEntry**)os::malloc(s);
+ JvmtiTagHashmapEntry** new_table = (JvmtiTagHashmapEntry**)os::malloc(s, mtInternal);
if (new_table == NULL) {
warning("unable to allocate larger hashtable for jvmti object tags");
set_resizing_enabled(false);
@@ -776,7 +776,7 @@
// For each field it holds the field index (as defined by the JVMTI specification),
// the field type, and the offset.
-class ClassFieldDescriptor: public CHeapObj {
+class ClassFieldDescriptor: public CHeapObj<mtInternal> {
private:
int _field_index;
int _field_offset;
@@ -790,7 +790,7 @@
int field_offset() const { return _field_offset; }
};
-class ClassFieldMap: public CHeapObj {
+class ClassFieldMap: public CHeapObj<mtInternal> {
private:
enum {
initial_field_count = 5
@@ -821,7 +821,8 @@
};
ClassFieldMap::ClassFieldMap() {
- _fields = new (ResourceObj::C_HEAP) GrowableArray<ClassFieldDescriptor*>(initial_field_count, true);
+ _fields = new (ResourceObj::C_HEAP, mtInternal)
+ GrowableArray<ClassFieldDescriptor*>(initial_field_count, true);
}
ClassFieldMap::~ClassFieldMap() {
@@ -892,7 +893,7 @@
// heap iteration and avoid creating a field map for each object in the heap
// (only need to create the map when the first instance of a class is encountered).
//
-class JvmtiCachedClassFieldMap : public CHeapObj {
+class JvmtiCachedClassFieldMap : public CHeapObj<mtInternal> {
private:
enum {
initial_class_count = 200
@@ -957,7 +958,8 @@
// record that the given instanceKlass is caching a field map
void JvmtiCachedClassFieldMap::add_to_class_list(instanceKlass* ik) {
if (_class_list == NULL) {
- _class_list = new (ResourceObj::C_HEAP) GrowableArray<instanceKlass*>(initial_class_count, true);
+ _class_list = new (ResourceObj::C_HEAP, mtInternal)
+ GrowableArray<instanceKlass*>(initial_class_count, true);
}
_class_list->push(ik);
}
@@ -1526,8 +1528,8 @@
_env = env;
_tags = (jlong*)tags;
_tag_count = tag_count;
- _object_results = new (ResourceObj::C_HEAP) GrowableArray<jobject>(1,true);
- _tag_results = new (ResourceObj::C_HEAP) GrowableArray<uint64_t>(1,true);
+ _object_results = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<jobject>(1,true);
+ _tag_results = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<uint64_t>(1,true);
}
~TagObjectCollector() {
@@ -1672,8 +1674,8 @@
Universe::heap()->ensure_parsability(false); // no need to retire TLABs
// create stacks for interesting headers
- _saved_mark_stack = new (ResourceObj::C_HEAP) GrowableArray<markOop>(4000, true);
- _saved_oop_stack = new (ResourceObj::C_HEAP) GrowableArray<oop>(4000, true);
+ _saved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<markOop>(4000, true);
+ _saved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(4000, true);
if (UseBiasedLocking) {
BiasedLocking::preserve_marks();
@@ -2712,7 +2714,7 @@
bool _reporting_string_values;
GrowableArray<oop>* create_visit_stack() {
- return new (ResourceObj::C_HEAP) GrowableArray<oop>(initial_visit_stack_size, true);
+ return new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(initial_visit_stack_size, true);
}
// accessors
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -41,7 +41,7 @@
class JvmtiTagHashmapEntry;
class JvmtiTagHashmapEntryClosure;
-class JvmtiTagMap : public CHeapObj {
+class JvmtiTagMap : public CHeapObj<mtInternal> {
private:
enum{
--- a/hotspot/src/share/vm/prims/jvmtiThreadState.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiThreadState.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -72,7 +72,7 @@
//
// The Jvmti state for each thread (across all JvmtiEnv):
// 1. Local table of enabled events.
-class JvmtiThreadState : public CHeapObj {
+class JvmtiThreadState : public CHeapObj<mtInternal> {
private:
friend class JvmtiEnv;
JavaThread *_thread;
--- a/hotspot/src/share/vm/prims/jvmtiUtil.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/jvmtiUtil.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
if (_single_threaded_resource_area == NULL) {
// lazily create the single threaded resource area
// pick a size which is not a standard since the pools don't exist yet
- _single_threaded_resource_area = new ResourceArea(Chunk::non_pool_size);
+ _single_threaded_resource_area = new (mtInternal) ResourceArea(Chunk::non_pool_size);
}
return _single_threaded_resource_area;
}
--- a/hotspot/src/share/vm/prims/unsafe.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/unsafe.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -596,7 +596,7 @@
return 0;
}
sz = round_to(sz, HeapWordSize);
- void* x = os::malloc(sz);
+ void* x = os::malloc(sz, mtInternal);
if (x == NULL) {
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
@@ -616,7 +616,7 @@
return 0;
}
sz = round_to(sz, HeapWordSize);
- void* x = (p == NULL) ? os::malloc(sz) : os::realloc(p, sz);
+ void* x = (p == NULL) ? os::malloc(sz, mtInternal) : os::realloc(p, sz, mtInternal);
if (x == NULL) {
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
@@ -877,7 +877,7 @@
return 0;
}
- body = NEW_C_HEAP_ARRAY(jbyte, length);
+ body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal);
if (body == 0) {
throw_new(env, "OutOfMemoryError");
@@ -893,7 +893,7 @@
uint len = env->GetStringUTFLength(name);
int unicode_len = env->GetStringLength(name);
if (len >= sizeof(buf)) {
- utfName = NEW_C_HEAP_ARRAY(char, len + 1);
+ utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
if (utfName == NULL) {
throw_new(env, "OutOfMemoryError");
goto free_body;
@@ -913,10 +913,10 @@
result = JVM_DefineClass(env, utfName, loader, body, length, pd);
if (utfName && utfName != buf)
- FREE_C_HEAP_ARRAY(char, utfName);
+ FREE_C_HEAP_ARRAY(char, utfName, mtInternal);
free_body:
- FREE_C_HEAP_ARRAY(jbyte, body);
+ FREE_C_HEAP_ARRAY(jbyte, body, mtInternal);
return result;
}
}
@@ -1011,7 +1011,7 @@
jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length();
jint word_length = (length + sizeof(HeapWord)-1) / sizeof(HeapWord);
- HeapWord* body = NEW_C_HEAP_ARRAY(HeapWord, word_length);
+ HeapWord* body = NEW_C_HEAP_ARRAY(HeapWord, word_length, mtInternal);
if (body == NULL) {
THROW_0(vmSymbols::java_lang_OutOfMemoryError());
}
@@ -1095,7 +1095,7 @@
// try/finally clause:
if (temp_alloc != NULL) {
- FREE_C_HEAP_ARRAY(HeapWord, temp_alloc);
+ FREE_C_HEAP_ARRAY(HeapWord, temp_alloc, mtInternal);
}
return (jclass) res_jh;
--- a/hotspot/src/share/vm/prims/whitebox.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/prims/whitebox.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -113,6 +113,9 @@
int offset = offset_for_field(field_name, object,
vmSymbols::string_signature());
oop string = object->obj_field(offset);
+ if (string == NULL) {
+ return NULL;
+ }
const char* ret = java_lang_String::as_utf8_string(string);
return ret;
}
--- a/hotspot/src/share/vm/runtime/arguments.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,6 +35,7 @@
#include "runtime/globals_extension.hpp"
#include "runtime/java.hpp"
#include "services/management.hpp"
+#include "services/memTracker.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/taskqueue.hpp"
#ifdef TARGET_OS_FAMILY_linux
@@ -368,7 +369,7 @@
inline void SysClassPath::reset_item_at(int index) {
assert(index < _scp_nitems && index != _scp_base, "just checking");
if (_items[index] != NULL) {
- FREE_C_HEAP_ARRAY(char, _items[index]);
+ FREE_C_HEAP_ARRAY(char, _items[index], mtInternal);
_items[index] = NULL;
}
}
@@ -400,11 +401,11 @@
expanded_path = add_jars_to_path(expanded_path, path);
path = end;
} else {
- char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1);
+ char* dirpath = NEW_C_HEAP_ARRAY(char, tmp_end - path + 1, mtInternal);
memcpy(dirpath, path, tmp_end - path);
dirpath[tmp_end - path] = '\0';
expanded_path = add_jars_to_path(expanded_path, dirpath);
- FREE_C_HEAP_ARRAY(char, dirpath);
+ FREE_C_HEAP_ARRAY(char, dirpath, mtInternal);
path = tmp_end + 1;
}
}
@@ -435,7 +436,7 @@
assert(total_len > 0, "empty sysclasspath not allowed");
// Copy the _items to a single string.
- char* cp = NEW_C_HEAP_ARRAY(char, total_len);
+ char* cp = NEW_C_HEAP_ARRAY(char, total_len, mtInternal);
char* cp_tmp = cp;
for (i = 0; i < _scp_nitems; ++i) {
if (_items[i] != NULL) {
@@ -456,7 +457,7 @@
assert(str != NULL, "just checking");
if (path == NULL) {
size_t len = strlen(str) + 1;
- cp = NEW_C_HEAP_ARRAY(char, len);
+ cp = NEW_C_HEAP_ARRAY(char, len, mtInternal);
memcpy(cp, str, len); // copy the trailing null
} else {
const char separator = *os::path_separator();
@@ -465,15 +466,15 @@
size_t len = old_len + str_len + 2;
if (prepend) {
- cp = NEW_C_HEAP_ARRAY(char, len);
+ cp = NEW_C_HEAP_ARRAY(char, len, mtInternal);
char* cp_tmp = cp;
memcpy(cp_tmp, str, str_len);
cp_tmp += str_len;
*cp_tmp = separator;
memcpy(++cp_tmp, path, old_len + 1); // copy the trailing null
- FREE_C_HEAP_ARRAY(char, path);
+ FREE_C_HEAP_ARRAY(char, path, mtInternal);
} else {
- cp = REALLOC_C_HEAP_ARRAY(char, path, len);
+ cp = REALLOC_C_HEAP_ARRAY(char, path, len, mtInternal);
char* cp_tmp = cp + old_len;
*cp_tmp = separator;
memcpy(++cp_tmp, str, str_len + 1); // copy the trailing null
@@ -495,7 +496,7 @@
/* Scan the directory for jars/zips, appending them to path. */
struct dirent *entry;
- char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory));
+ char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(directory), mtInternal);
while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL) {
const char* name = entry->d_name;
const char* ext = name + strlen(name) - 4;
@@ -503,13 +504,13 @@
(os::file_name_strcmp(ext, ".jar") == 0 ||
os::file_name_strcmp(ext, ".zip") == 0);
if (isJarOrZip) {
- char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name));
+ char* jarpath = NEW_C_HEAP_ARRAY(char, directory_len + 2 + strlen(name), mtInternal);
sprintf(jarpath, "%s%s%s", directory, dir_sep, name);
path = add_to_path(path, jarpath, false);
- FREE_C_HEAP_ARRAY(char, jarpath);
+ FREE_C_HEAP_ARRAY(char, jarpath, mtInternal);
}
}
- FREE_C_HEAP_ARRAY(char, dbuf);
+ FREE_C_HEAP_ARRAY(char, dbuf, mtInternal);
os::closedir(dir);
return path;
}
@@ -631,7 +632,7 @@
static bool set_string_flag(char* name, const char* value, FlagValueOrigin origin) {
if (!CommandLineFlags::ccstrAtPut(name, &value, origin)) return false;
// Contract: CommandLineFlags always returns a pointer that needs freeing.
- FREE_C_HEAP_ARRAY(char, value);
+ FREE_C_HEAP_ARRAY(char, value, mtInternal);
return true;
}
@@ -647,7 +648,7 @@
} else if (new_len == 0) {
value = old_value;
} else {
- char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1);
+ char* buf = NEW_C_HEAP_ARRAY(char, old_len + 1 + new_len + 1, mtInternal);
// each new setting adds another LINE to the switch:
sprintf(buf, "%s\n%s", old_value, new_value);
value = buf;
@@ -655,10 +656,10 @@
}
(void) CommandLineFlags::ccstrAtPut(name, &value, origin);
// CommandLineFlags always returns a pointer that needs freeing.
- FREE_C_HEAP_ARRAY(char, value);
+ FREE_C_HEAP_ARRAY(char, value, mtInternal);
if (free_this_too != NULL) {
// CommandLineFlags made its own copy, so I must delete my own temp. buffer.
- FREE_C_HEAP_ARRAY(char, free_this_too);
+ FREE_C_HEAP_ARRAY(char, free_this_too, mtInternal);
}
return true;
}
@@ -735,9 +736,9 @@
// expand the array and add arg to the last element
(*count)++;
if (*bldarray == NULL) {
- *bldarray = NEW_C_HEAP_ARRAY(char*, *count);
+ *bldarray = NEW_C_HEAP_ARRAY(char*, *count, mtInternal);
} else {
- *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, *count);
+ *bldarray = REALLOC_C_HEAP_ARRAY(char*, *bldarray, *count, mtInternal);
}
(*bldarray)[index] = strdup(arg);
}
@@ -917,13 +918,13 @@
char* value = (char *)ns;
size_t key_len = (eq == NULL) ? strlen(prop) : (eq - prop);
- key = AllocateHeap(key_len + 1, "add_property");
+ key = AllocateHeap(key_len + 1, mtInternal);
strncpy(key, prop, key_len);
key[key_len] = '\0';
if (eq != NULL) {
size_t value_len = strlen(prop) - key_len - 1;
- value = AllocateHeap(value_len + 1, "add_property");
+ value = AllocateHeap(value_len + 1, mtInternal);
strncpy(value, &prop[key_len + 1], value_len + 1);
}
@@ -2058,12 +2059,12 @@
const char* altclasses_jar = "alt-rt.jar";
size_t altclasses_path_len = strlen(get_meta_index_dir()) + 1 +
strlen(altclasses_jar);
- char* altclasses_path = NEW_C_HEAP_ARRAY(char, altclasses_path_len);
+ char* altclasses_path = NEW_C_HEAP_ARRAY(char, altclasses_path_len, mtInternal);
strcpy(altclasses_path, get_meta_index_dir());
strcat(altclasses_path, altclasses_jar);
scp.add_suffix_to_prefix(altclasses_path);
scp_assembly_required = true;
- FREE_C_HEAP_ARRAY(char, altclasses_path);
+ FREE_C_HEAP_ARRAY(char, altclasses_path, mtInternal);
}
if (WhiteBoxAPI) {
@@ -2071,12 +2072,12 @@
const char* wb_jar = "wb.jar";
size_t wb_path_len = strlen(get_meta_index_dir()) + 1 +
strlen(wb_jar);
- char* wb_path = NEW_C_HEAP_ARRAY(char, wb_path_len);
+ char* wb_path = NEW_C_HEAP_ARRAY(char, wb_path_len, mtInternal);
strcpy(wb_path, get_meta_index_dir());
strcat(wb_path, wb_jar);
scp.add_suffix(wb_path);
scp_assembly_required = true;
- FREE_C_HEAP_ARRAY(char, wb_path);
+ FREE_C_HEAP_ARRAY(char, wb_path, mtInternal);
}
// Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM)
@@ -2161,13 +2162,13 @@
if (tail != NULL) {
const char* pos = strchr(tail, ':');
size_t len = (pos == NULL) ? strlen(tail) : pos - tail;
- char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1), tail, len);
+ char* name = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len);
name[len] = '\0';
char *options = NULL;
if(pos != NULL) {
size_t len2 = strlen(pos+1) + 1; // options start after ':'. Final zero must be copied.
- options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2), pos+1, len2);
+ options = (char*)memcpy(NEW_C_HEAP_ARRAY(char, len2, mtInternal), pos+1, len2);
}
#ifdef JVMTI_KERNEL
if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {
@@ -2182,12 +2183,12 @@
if(tail != NULL) {
const char* pos = strchr(tail, '=');
size_t len = (pos == NULL) ? strlen(tail) : pos - tail;
- char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1), tail, len);
+ char* name = strncpy(NEW_C_HEAP_ARRAY(char, len + 1, mtInternal), tail, len);
name[len] = '\0';
char *options = NULL;
if(pos != NULL) {
- options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(pos + 1) + 1), pos + 1);
+ options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(pos + 1) + 1, mtInternal), pos + 1);
}
#ifdef JVMTI_KERNEL
if ((strcmp(name, "hprof") == 0) || (strcmp(name, "jdwp") == 0)) {
@@ -2200,7 +2201,7 @@
// -javaagent
} else if (match_option(option, "-javaagent:", &tail)) {
if(tail != NULL) {
- char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1), tail);
+ char *options = strcpy(NEW_C_HEAP_ARRAY(char, strlen(tail) + 1, mtInternal), tail);
add_init_agent("instrument", options, false);
}
// -Xnoclassgc
@@ -2708,6 +2709,17 @@
return JNI_EINVAL;
}
FLAG_SET_CMDLINE(uintx, ConcGCThreads, conc_threads);
+ } else if (match_option(option, "-XX:MaxDirectMemorySize=", &tail)) {
+ julong max_direct_memory_size = 0;
+ ArgsRange errcode = parse_memory_size(tail, &max_direct_memory_size, 0);
+ if (errcode != arg_in_range) {
+ jio_fprintf(defaultStream::error_stream(),
+ "Invalid maximum direct memory size: %s\n",
+ option->optionString);
+ describe_range_error(errcode);
+ return JNI_EINVAL;
+ }
+ FLAG_SET_CMDLINE(uintx, MaxDirectMemorySize, max_direct_memory_size);
} else if (match_option(option, "-XX:", &tail)) { // -XX:xxxx
// Skip -XX:Flags= since that case has already been handled
if (strncmp(tail, "Flags=", strlen("Flags=")) != 0) {
@@ -2958,7 +2970,7 @@
char *end = strrchr(jvm_path, *os::file_separator());
if (end != NULL) *end = '\0';
char *shared_archive_path = NEW_C_HEAP_ARRAY(char, strlen(jvm_path) +
- strlen(os::file_separator()) + 20);
+ strlen(os::file_separator()) + 20, mtInternal);
if (shared_archive_path == NULL) return JNI_ENOMEM;
strcpy(shared_archive_path, jvm_path);
strcat(shared_archive_path, os::file_separator());
@@ -2971,7 +2983,10 @@
const char* tail;
// If flag "-XX:Flags=flags-file" is used it will be the first option to be processed.
+ const char* hotspotrc = ".hotspotrc";
bool settings_file_specified = false;
+ bool needs_hotspotrc_warning = false;
+
const char* flags_file;
int index;
for (index = 0; index < args->nOptions; index++) {
@@ -2996,6 +3011,10 @@
CommandLineFlags::printFlags(tty, false);
vm_exit(0);
}
+ if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
+ MemTracker::init_tracking_options(tail);
+ }
+
#ifndef PRODUCT
if (match_option(option, "-XX:+PrintFlagsWithComments", &tail)) {
@@ -3015,16 +3034,19 @@
if (!process_settings_file(flags_file, true, args->ignoreUnrecognized)) {
return JNI_EINVAL;
}
- }
-
+ } else {
#ifdef ASSERT
- // Parse default .hotspotrc settings file
- if (!settings_file_specified) {
+ // Parse default .hotspotrc settings file
if (!process_settings_file(".hotspotrc", false, args->ignoreUnrecognized)) {
return JNI_EINVAL;
}
+#else
+ struct stat buf;
+ if (os::stat(hotspotrc, &buf) == 0) {
+ needs_hotspotrc_warning = true;
+ }
+#endif
}
-#endif
if (PrintVMOptions) {
for (index = 0; index < args->nOptions; index++) {
@@ -3041,6 +3063,14 @@
return result;
}
+ // Delay warning until here so that we've had a chance to process
+ // the -XX:-PrintWarnings flag
+ if (needs_hotspotrc_warning) {
+ warning("%s file is present but has been ignored. "
+ "Run with -XX:Flags=%s to load the file.",
+ hotspotrc, hotspotrc);
+ }
+
#if (defined JAVASE_EMBEDDED || defined ARM)
UNSUPPORTED_OPTION(UseG1GC, "G1 GC");
#endif
@@ -3333,7 +3363,7 @@
}
}
// Add one for null terminator.
- char *props = AllocateHeap(length + 1, "get_kernel_properties");
+ char *props = AllocateHeap(length + 1, mtInternal);
if (length != 0) {
int pos = 0;
for (prop = _system_properties; prop != NULL; prop = prop->next()) {
--- a/hotspot/src/share/vm/runtime/arguments.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/arguments.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -44,7 +44,7 @@
// Element describing System and User (-Dkey=value flags) defined property.
-class SystemProperty: public CHeapObj {
+class SystemProperty: public CHeapObj<mtInternal> {
private:
char* _key;
char* _value;
@@ -63,7 +63,7 @@
if (_value != NULL) {
FreeHeap(_value);
}
- _value = AllocateHeap(strlen(value)+1);
+ _value = AllocateHeap(strlen(value)+1, mtInternal);
if (_value != NULL) {
strcpy(_value, value);
}
@@ -80,7 +80,7 @@
if (_value != NULL) {
len += strlen(_value);
}
- sp = AllocateHeap(len+2);
+ sp = AllocateHeap(len+2, mtInternal);
if (sp != NULL) {
if (_value != NULL) {
strcpy(sp, _value);
@@ -100,13 +100,13 @@
if (key == NULL) {
_key = NULL;
} else {
- _key = AllocateHeap(strlen(key)+1);
+ _key = AllocateHeap(strlen(key)+1, mtInternal);
strcpy(_key, key);
}
if (value == NULL) {
_value = NULL;
} else {
- _value = AllocateHeap(strlen(value)+1);
+ _value = AllocateHeap(strlen(value)+1, mtInternal);
strcpy(_value, value);
}
_next = NULL;
@@ -116,7 +116,7 @@
// For use by -agentlib, -agentpath and -Xrun
-class AgentLibrary : public CHeapObj {
+class AgentLibrary : public CHeapObj<mtInternal> {
friend class AgentLibraryList;
private:
char* _name;
@@ -136,12 +136,12 @@
// Constructor
AgentLibrary(const char* name, const char* options, bool is_absolute_path, void* os_lib) {
- _name = AllocateHeap(strlen(name)+1);
+ _name = AllocateHeap(strlen(name)+1, mtInternal);
strcpy(_name, name);
if (options == NULL) {
_options = NULL;
} else {
- _options = AllocateHeap(strlen(options)+1);
+ _options = AllocateHeap(strlen(options)+1, mtInternal);
strcpy(_options, options);
}
_is_absolute_path = is_absolute_path;
--- a/hotspot/src/share/vm/runtime/biasedLocking.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -687,8 +687,8 @@
// monitors in a prepass and, if they are biased, preserve their
// mark words here. This should be a relatively small set of objects
// especially compared to the number of objects in the heap.
- _preserved_mark_stack = new (ResourceObj::C_HEAP) GrowableArray<markOop>(10, true);
- _preserved_oop_stack = new (ResourceObj::C_HEAP) GrowableArray<Handle>(10, true);
+ _preserved_mark_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<markOop>(10, true);
+ _preserved_oop_stack = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Handle>(10, true);
ResourceMark rm;
Thread* cur = Thread::current();
--- a/hotspot/src/share/vm/runtime/compilationPolicy.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/compilationPolicy.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -37,7 +37,7 @@
class CompileTask;
class CompileQueue;
-class CompilationPolicy : public CHeapObj {
+class CompilationPolicy : public CHeapObj<mtCompiler> {
static CompilationPolicy* _policy;
// Accumulated time
static elapsedTimer _accumulated_time;
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -101,7 +101,7 @@
_number_of_frames = number_of_frames;
_frame_sizes = frame_sizes;
_frame_pcs = frame_pcs;
- _register_block = NEW_C_HEAP_ARRAY(intptr_t, RegisterMap::reg_count * 2);
+ _register_block = NEW_C_HEAP_ARRAY(intptr_t, RegisterMap::reg_count * 2, mtCompiler);
_return_type = return_type;
_initial_info = 0;
// PD (x86 only)
@@ -114,9 +114,9 @@
Deoptimization::UnrollBlock::~UnrollBlock() {
- FREE_C_HEAP_ARRAY(intptr_t, _frame_sizes);
- FREE_C_HEAP_ARRAY(intptr_t, _frame_pcs);
- FREE_C_HEAP_ARRAY(intptr_t, _register_block);
+ FREE_C_HEAP_ARRAY(intptr_t, _frame_sizes, mtCompiler);
+ FREE_C_HEAP_ARRAY(intptr_t, _frame_pcs, mtCompiler);
+ FREE_C_HEAP_ARRAY(intptr_t, _register_block, mtCompiler);
}
@@ -358,9 +358,9 @@
// Compute the vframes' sizes. Note that frame_sizes[] entries are ordered from outermost to innermost
// virtual activation, which is the reverse of the elements in the vframes array.
- intptr_t* frame_sizes = NEW_C_HEAP_ARRAY(intptr_t, number_of_frames);
+ intptr_t* frame_sizes = NEW_C_HEAP_ARRAY(intptr_t, number_of_frames, mtCompiler);
// +1 because we always have an interpreter return address for the final slot.
- address* frame_pcs = NEW_C_HEAP_ARRAY(address, number_of_frames + 1);
+ address* frame_pcs = NEW_C_HEAP_ARRAY(address, number_of_frames + 1, mtCompiler);
int popframe_extra_args = 0;
// Create an interpreter return address for the stub to use as its return
// address so the skeletal frames are perfectly walkable
--- a/hotspot/src/share/vm/runtime/deoptimization.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/deoptimization.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -129,7 +129,7 @@
// UnrollBlock is returned by fetch_unroll_info() to the deoptimization handler (blob).
// This is only a CheapObj to ease debugging after a deopt failure
- class UnrollBlock : public CHeapObj {
+ class UnrollBlock : public CHeapObj<mtCompiler> {
private:
int _size_of_deoptimized_frame; // Size, in bytes, of current deoptimized frame
int _caller_adjustment; // Adjustment, in bytes, to caller's SP by initial interpreted frame
--- a/hotspot/src/share/vm/runtime/dtraceJSDT.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/dtraceJSDT.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -63,7 +63,7 @@
static jboolean is_supported();
};
-class RegisteredProbes : public CHeapObj {
+class RegisteredProbes : public CHeapObj<mtInternal> {
private:
nmethod** _nmethods; // all the probe methods
size_t _count; // number of probe methods
@@ -72,7 +72,7 @@
public:
RegisteredProbes(size_t count) {
_count = count;
- _nmethods = NEW_C_HEAP_ARRAY(nmethod*, count);
+ _nmethods = NEW_C_HEAP_ARRAY(nmethod*, count, mtInternal);
}
~RegisteredProbes() {
@@ -81,7 +81,7 @@
_nmethods[i]->make_not_entrant();
_nmethods[i]->method()->clear_code();
}
- FREE_C_HEAP_ARRAY(nmethod*, _nmethods);
+ FREE_C_HEAP_ARRAY(nmethod*, _nmethods, mtInternal);
_nmethods = NULL;
_count = 0;
}
--- a/hotspot/src/share/vm/runtime/fprofiler.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/fprofiler.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -70,12 +70,12 @@
ThreadProfiler::ThreadProfiler() {
// Space for the ProfilerNodes
const int area_size = 1 * ProfilerNodeSize * 1024;
- area_bottom = AllocateHeap(area_size, "fprofiler");
+ area_bottom = AllocateHeap(area_size, mtInternal);
area_top = area_bottom;
area_limit = area_bottom + area_size;
// ProfilerNode pointer table
- table = NEW_C_HEAP_ARRAY(ProfilerNode*, table_size);
+ table = NEW_C_HEAP_ARRAY(ProfilerNode*, table_size, mtInternal);
initialize();
engaged = false;
}
@@ -157,7 +157,7 @@
void PCRecorder::init() {
MutexLockerEx lm(CodeCache_lock, Mutex::_no_safepoint_check_flag);
int s = size();
- counters = NEW_C_HEAP_ARRAY(int, s);
+ counters = NEW_C_HEAP_ARRAY(int, s, mtInternal);
for (int index = 0; index < s; index++) {
counters[index] = 0;
}
@@ -850,7 +850,7 @@
if (Threads_lock->try_lock()) {
{ // Threads_lock scope
maxthreads = Threads::number_of_threads();
- threadsList = NEW_C_HEAP_ARRAY(JavaThread *, maxthreads);
+ threadsList = NEW_C_HEAP_ARRAY(JavaThread *, maxthreads, mtInternal);
suspendedthreadcount = 0;
for (JavaThread* tp = Threads::first(); tp != NULL; tp = tp->next()) {
if (tp->is_Compiler_thread()) {
@@ -1195,8 +1195,8 @@
void FlatProfiler::allocate_table() {
{ // Bytecode table
- bytecode_ticks = NEW_C_HEAP_ARRAY(int, Bytecodes::number_of_codes);
- bytecode_ticks_stub = NEW_C_HEAP_ARRAY(int, Bytecodes::number_of_codes);
+ bytecode_ticks = NEW_C_HEAP_ARRAY(int, Bytecodes::number_of_codes, mtInternal);
+ bytecode_ticks_stub = NEW_C_HEAP_ARRAY(int, Bytecodes::number_of_codes, mtInternal);
for(int index = 0; index < Bytecodes::number_of_codes; index++) {
bytecode_ticks[index] = 0;
bytecode_ticks_stub[index] = 0;
@@ -1205,7 +1205,7 @@
if (ProfilerRecordPC) PCRecorder::init();
- interval_data = NEW_C_HEAP_ARRAY(IntervalData, interval_print_size);
+ interval_data = NEW_C_HEAP_ARRAY(IntervalData, interval_print_size, mtInternal);
FlatProfiler::interval_reset();
}
--- a/hotspot/src/share/vm/runtime/fprofiler.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/fprofiler.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -121,7 +121,7 @@
};
#endif // FPROF_KERNEL
-class ThreadProfiler: public CHeapObj {
+class ThreadProfiler: public CHeapObj<mtInternal> {
public:
ThreadProfiler() KERNEL_RETURN;
~ThreadProfiler() KERNEL_RETURN;
--- a/hotspot/src/share/vm/runtime/globals.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/globals.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -465,13 +465,13 @@
ccstr old_value = result->get_ccstr();
char* new_value = NULL;
if (*value != NULL) {
- new_value = NEW_C_HEAP_ARRAY(char, strlen(*value)+1);
+ new_value = NEW_C_HEAP_ARRAY(char, strlen(*value)+1, mtInternal);
strcpy(new_value, *value);
}
result->set_ccstr(new_value);
if (result->origin == DEFAULT && old_value != NULL) {
// Prior value is NOT heap allocated, but was a literal constant.
- char* old_value_to_free = NEW_C_HEAP_ARRAY(char, strlen(old_value)+1);
+ char* old_value_to_free = NEW_C_HEAP_ARRAY(char, strlen(old_value)+1, mtInternal);
strcpy(old_value_to_free, old_value);
old_value = old_value_to_free;
}
@@ -485,12 +485,12 @@
Flag* faddr = address_of_flag(flag);
guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
ccstr old_value = faddr->get_ccstr();
- char* new_value = NEW_C_HEAP_ARRAY(char, strlen(value)+1);
+ char* new_value = NEW_C_HEAP_ARRAY(char, strlen(value)+1, mtInternal);
strcpy(new_value, value);
faddr->set_ccstr(new_value);
if (faddr->origin != DEFAULT && old_value != NULL) {
// Prior value is heap allocated so free it.
- FREE_C_HEAP_ARRAY(char, old_value);
+ FREE_C_HEAP_ARRAY(char, old_value, mtInternal);
}
faddr->origin = origin;
}
@@ -511,7 +511,7 @@
while (flagTable[length].name != NULL) length++;
// Sort
- Flag** array = NEW_C_HEAP_ARRAY(Flag*, length);
+ Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
for (int index = 0; index < length; index++) {
array[index] = &flagTable[index];
}
@@ -525,7 +525,7 @@
}
}
out->cr();
- FREE_C_HEAP_ARRAY(Flag*, array);
+ FREE_C_HEAP_ARRAY(Flag*, array, mtInternal);
}
#ifndef PRODUCT
@@ -547,7 +547,7 @@
while (flagTable[length].name != NULL) length++;
// Sort
- Flag** array = NEW_C_HEAP_ARRAY(Flag*, length);
+ Flag** array = NEW_C_HEAP_ARRAY(Flag*, length, mtInternal);
for (int index = 0; index < length; index++) {
array[index] = &flagTable[index];
}
@@ -560,5 +560,5 @@
array[i]->print_on(out, withComments);
}
}
- FREE_C_HEAP_ARRAY(Flag*, array);
+ FREE_C_HEAP_ARRAY(Flag*, array, mtInternal);
}
--- a/hotspot/src/share/vm/runtime/globals.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/globals.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -190,7 +190,6 @@
#endif // no compilers
-
// string type aliases used only in this file
typedef const char* ccstr;
typedef const char* ccstrlist; // represents string arguments which accumulate
@@ -896,6 +895,9 @@
develop(bool, UseFakeTimers, false, \
"Tells whether the VM should use system time or a fake timer") \
\
+ product(ccstr, NativeMemoryTracking, "off", \
+ "Native memory tracking options") \
+ \
diagnostic(bool, LogCompilation, false, \
"Log compilation activity in detail to hotspot.log or LogFile") \
\
@@ -3703,7 +3705,7 @@
\
/* Properties for Java libraries */ \
\
- product(intx, MaxDirectMemorySize, -1, \
+ product(uintx, MaxDirectMemorySize, 0, \
"Maximum total size of NIO direct-buffer allocations") \
\
/* temporary developer defined flags */ \
--- a/hotspot/src/share/vm/runtime/handles.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/handles.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -111,7 +111,7 @@
_chunk = _area->_chunk;
_hwm = _area->_hwm;
_max = _area->_max;
- NOT_PRODUCT(_size_in_bytes = _area->_size_in_bytes;)
+ _size_in_bytes = _area->_size_in_bytes;
debug_only(_area->_handle_mark_nesting++);
assert(_area->_handle_mark_nesting > 0, "must stack allocate HandleMarks");
debug_only(Atomic::inc(&_nof_handlemarks);)
@@ -159,7 +159,7 @@
area->_chunk = _chunk;
area->_hwm = _hwm;
area->_max = _max;
- NOT_PRODUCT(area->set_size_in_bytes(_size_in_bytes);)
+ area->set_size_in_bytes(_size_in_bytes);
#ifdef ASSERT
// clear out first chunk (to detect allocation bugs)
if (ZapVMHandleArea) {
--- a/hotspot/src/share/vm/runtime/handles.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/handles.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -238,7 +238,6 @@
//------------------------------------------------------------------------------------------------------------------------
// Thread local handle area
-
class HandleArea: public Arena {
friend class HandleMark;
friend class NoHandleMark;
@@ -312,7 +311,7 @@
HandleArea *_area; // saved handle area
Chunk *_chunk; // saved arena chunk
char *_hwm, *_max; // saved arena info
- NOT_PRODUCT(size_t _size_in_bytes;) // size of handle area
+ size_t _size_in_bytes; // size of handle area
// Link to previous active HandleMark in thread
HandleMark* _previous_handle_mark;
--- a/hotspot/src/share/vm/runtime/handles.inline.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/handles.inline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -85,7 +85,7 @@
area->_chunk = _chunk;
area->_hwm = _hwm;
area->_max = _max;
- NOT_PRODUCT(area->set_size_in_bytes(_size_in_bytes);)
+ area->set_size_in_bytes(_size_in_bytes);
debug_only(area->_handle_mark_nesting--);
}
--- a/hotspot/src/share/vm/runtime/java.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/java.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -384,7 +384,7 @@
typedef void (*__exit_proc)(void);
}
-class ExitProc : public CHeapObj {
+class ExitProc : public CHeapObj<mtInternal> {
private:
__exit_proc _proc;
// void (*_proc)(void);
--- a/hotspot/src/share/vm/runtime/jniHandles.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/jniHandles.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -109,7 +109,7 @@
// JNI handle blocks holding local/global JNI handles
-class JNIHandleBlock : public CHeapObj {
+class JNIHandleBlock : public CHeapObj<mtInternal> {
friend class VMStructs;
friend class CppInterpreter;
--- a/hotspot/src/share/vm/runtime/monitorChunk.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/monitorChunk.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -29,7 +29,7 @@
MonitorChunk::MonitorChunk(int number_on_monitors) {
_number_of_monitors = number_on_monitors;
- _monitors = NEW_C_HEAP_ARRAY(BasicObjectLock, number_on_monitors);
+ _monitors = NEW_C_HEAP_ARRAY(BasicObjectLock, number_on_monitors, mtInternal);
_next = NULL;
}
--- a/hotspot/src/share/vm/runtime/monitorChunk.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/monitorChunk.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -30,7 +30,7 @@
// Data structure for holding monitors for one activation during
// deoptimization.
-class MonitorChunk: public CHeapObj {
+class MonitorChunk: public CHeapObj<mtInternal> {
private:
int _number_of_monitors;
BasicObjectLock* _monitors;
--- a/hotspot/src/share/vm/runtime/mutex.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/mutex.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -84,7 +84,7 @@
// The default length of monitor name is chosen to be 64 to avoid false sharing.
static const int MONITOR_NAME_LEN = 64;
-class Monitor : public CHeapObj {
+class Monitor : public CHeapObj<mtInternal> {
public:
// A special lock: Is a lock where you are guaranteed not to block while you are
--- a/hotspot/src/share/vm/runtime/os.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/os.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -45,6 +45,7 @@
#include "runtime/os.hpp"
#include "runtime/stubRoutines.hpp"
#include "services/attachListener.hpp"
+#include "services/memTracker.hpp"
#include "services/threadService.hpp"
#include "utilities/defaultStream.hpp"
#include "utilities/events.hpp"
@@ -433,9 +434,9 @@
// --------------------- heap allocation utilities ---------------------
-char *os::strdup(const char *str) {
+char *os::strdup(const char *str, MEMFLAGS flags) {
size_t size = strlen(str);
- char *dup_str = (char *)malloc(size + 1);
+ char *dup_str = (char *)malloc(size + 1, flags);
if (dup_str == NULL) return NULL;
strcpy(dup_str, str);
return dup_str;
@@ -559,7 +560,7 @@
}
#endif
-void* os::malloc(size_t size) {
+void* os::malloc(size_t size, MEMFLAGS memflags, address caller) {
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
@@ -571,6 +572,7 @@
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
u_char* ptr = (u_char*)::malloc(size + space_before + space_after);
+
#ifdef ASSERT
if (ptr == NULL) return NULL;
if (MallocCushion) {
@@ -589,18 +591,29 @@
}
debug_only(if (paranoid) verify_block(memblock));
if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock);
+
+ // we do not track MallocCushion memory
+ if (MemTracker::is_on()) {
+ MemTracker::record_malloc((address)memblock, size, memflags, caller == 0 ? CALLER_PC : caller);
+ }
+
return memblock;
}
-void* os::realloc(void *memblock, size_t size) {
+void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) {
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
- return ::realloc(memblock, size);
+ void* ptr = ::realloc(memblock, size);
+ if (ptr != NULL && MemTracker::is_on()) {
+ MemTracker::record_realloc((address)memblock, (address)ptr, size, memflags,
+ caller == 0 ? CALLER_PC : caller);
+ }
+ return ptr;
#else
if (memblock == NULL) {
- return malloc(size);
+ return malloc(size, memflags, (caller == 0 ? CALLER_PC : caller));
}
if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
tty->print_cr("os::realloc caught " PTR_FORMAT, memblock);
@@ -610,7 +623,7 @@
NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
if (size == 0) return NULL;
// always move the block
- void* ptr = malloc(size);
+ void* ptr = malloc(size, memflags, caller == 0 ? CALLER_PC : caller);
if (PrintMalloc) tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr);
// Copy to new memory if malloc didn't fail
if ( ptr != NULL ) {
@@ -627,7 +640,7 @@
}
-void os::free(void *memblock) {
+void os::free(void *memblock, MEMFLAGS memflags) {
NOT_PRODUCT(inc_stat_counter(&num_frees, 1));
#ifdef ASSERT
if (memblock == NULL) return;
@@ -660,6 +673,8 @@
fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock);
}
#endif
+ MemTracker::record_free((address)memblock, memflags);
+
::free((char*)memblock - space_before);
}
@@ -1048,7 +1063,7 @@
++formatted_path_len;
}
- char* formatted_path = NEW_C_HEAP_ARRAY(char, formatted_path_len + 1);
+ char* formatted_path = NEW_C_HEAP_ARRAY(char, formatted_path_len + 1, mtInternal);
if (formatted_path == NULL) {
return NULL;
}
@@ -1127,7 +1142,7 @@
return NULL;
}
const char psepchar = *os::path_separator();
- char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1);
+ char* inpath = (char*)NEW_C_HEAP_ARRAY(char, strlen(path) + 1, mtInternal);
if (inpath == NULL) {
return NULL;
}
@@ -1140,7 +1155,7 @@
p++;
p = strchr(p, psepchar);
}
- char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count);
+ char** opath = (char**) NEW_C_HEAP_ARRAY(char*, count, mtInternal);
if (opath == NULL) {
return NULL;
}
@@ -1153,7 +1168,7 @@
return NULL;
}
// allocate the string and add terminator storage
- char* s = (char*)NEW_C_HEAP_ARRAY(char, len + 1);
+ char* s = (char*)NEW_C_HEAP_ARRAY(char, len + 1, mtInternal);
if (s == NULL) {
return NULL;
}
@@ -1162,7 +1177,7 @@
opath[i] = s;
p += len + 1;
}
- FREE_C_HEAP_ARRAY(char, inpath);
+ FREE_C_HEAP_ARRAY(char, inpath, mtInternal);
*n = count;
return opath;
}
@@ -1366,3 +1381,97 @@
return (int) i;
}
+
+bool os::create_stack_guard_pages(char* addr, size_t bytes) {
+ return os::pd_create_stack_guard_pages(addr, bytes);
+}
+
+
+char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
+ char* result = pd_reserve_memory(bytes, addr, alignment_hint);
+ if (result != NULL && MemTracker::is_on()) {
+ MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
+ }
+
+ return result;
+}
+char* os::attempt_reserve_memory_at(size_t bytes, char* addr) {
+ char* result = pd_attempt_reserve_memory_at(bytes, addr);
+ if (result != NULL && MemTracker::is_on()) {
+ MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
+ }
+ return result;
+}
+
+void os::split_reserved_memory(char *base, size_t size,
+ size_t split, bool realloc) {
+ pd_split_reserved_memory(base, size, split, realloc);
+}
+
+bool os::commit_memory(char* addr, size_t bytes, bool executable) {
+ bool res = pd_commit_memory(addr, bytes, executable);
+ if (res && MemTracker::is_on()) {
+ MemTracker::record_virtual_memory_commit((address)addr, bytes, CALLER_PC);
+ }
+ return res;
+}
+
+bool os::commit_memory(char* addr, size_t size, size_t alignment_hint,
+ bool executable) {
+ bool res = os::pd_commit_memory(addr, size, alignment_hint, executable);
+ if (res && MemTracker::is_on()) {
+ MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC);
+ }
+ return res;
+}
+
+bool os::uncommit_memory(char* addr, size_t bytes) {
+ bool res = pd_uncommit_memory(addr, bytes);
+ if (res) {
+ MemTracker::record_virtual_memory_uncommit((address)addr, bytes);
+ }
+ return res;
+}
+
+bool os::release_memory(char* addr, size_t bytes) {
+ bool res = pd_release_memory(addr, bytes);
+ if (res) {
+ MemTracker::record_virtual_memory_release((address)addr, bytes);
+ }
+ return res;
+}
+
+
+char* os::map_memory(int fd, const char* file_name, size_t file_offset,
+ char *addr, size_t bytes, bool read_only,
+ bool allow_exec) {
+ char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec);
+ if (result != NULL && MemTracker::is_on()) {
+ MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
+ }
+ return result;
+}
+
+char* os::remap_memory(int fd, const char* file_name, size_t file_offset,
+ char *addr, size_t bytes, bool read_only,
+ bool allow_exec) {
+ return pd_remap_memory(fd, file_name, file_offset, addr, bytes,
+ read_only, allow_exec);
+}
+
+bool os::unmap_memory(char *addr, size_t bytes) {
+ bool result = pd_unmap_memory(addr, bytes);
+ if (result) {
+ MemTracker::record_virtual_memory_release((address)addr, bytes);
+ }
+ return result;
+}
+
+void os::free_memory(char *addr, size_t bytes, size_t alignment_hint) {
+ pd_free_memory(addr, bytes, alignment_hint);
+}
+
+void os::realign_memory(char *addr, size_t bytes, size_t alignment_hint) {
+ pd_realign_memory(addr, bytes, alignment_hint);
+}
+
--- a/hotspot/src/share/vm/runtime/os.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/os.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -99,6 +99,28 @@
_page_sizes[1] = 0; // sentinel
}
+ static char* pd_reserve_memory(size_t bytes, char* addr = 0,
+ size_t alignment_hint = 0);
+ static char* pd_attempt_reserve_memory_at(size_t bytes, char* addr);
+ static void pd_split_reserved_memory(char *base, size_t size,
+ size_t split, bool realloc);
+ static bool pd_commit_memory(char* addr, size_t bytes, bool executable = false);
+ static bool pd_commit_memory(char* addr, size_t size, size_t alignment_hint,
+ bool executable = false);
+ static bool pd_uncommit_memory(char* addr, size_t bytes);
+ static bool pd_release_memory(char* addr, size_t bytes);
+
+ static char* pd_map_memory(int fd, const char* file_name, size_t file_offset,
+ char *addr, size_t bytes, bool read_only = false,
+ bool allow_exec = false);
+ static char* pd_remap_memory(int fd, const char* file_name, size_t file_offset,
+ char *addr, size_t bytes, bool read_only,
+ bool allow_exec);
+ static bool pd_unmap_memory(char *addr, size_t bytes);
+ static void pd_free_memory(char *addr, size_t bytes, size_t alignment_hint);
+ static void pd_realign_memory(char *addr, size_t bytes, size_t alignment_hint);
+
+
public:
static void init(void); // Called before command line parsing
static jint init_2(void); // Called after command line parsing
@@ -236,8 +258,7 @@
static char* attempt_reserve_memory_at(size_t bytes, char* addr);
static void split_reserved_memory(char *base, size_t size,
size_t split, bool realloc);
- static bool commit_memory(char* addr, size_t bytes,
- bool executable = false);
+ static bool commit_memory(char* addr, size_t bytes, bool executable = false);
static bool commit_memory(char* addr, size_t size, size_t alignment_hint,
bool executable = false);
static bool uncommit_memory(char* addr, size_t bytes);
@@ -250,6 +271,7 @@
static bool guard_memory(char* addr, size_t bytes);
static bool unguard_memory(char* addr, size_t bytes);
static bool create_stack_guard_pages(char* addr, size_t bytes);
+ static bool pd_create_stack_guard_pages(char* addr, size_t bytes);
static bool remove_stack_guard_pages(char* addr, size_t bytes);
static char* map_memory(int fd, const char* file_name, size_t file_offset,
@@ -573,12 +595,15 @@
static void* thread_local_storage_at(int index);
static void free_thread_local_storage(int index);
+ // Stack walk
+ static address get_caller_pc(int n = 0);
+
// General allocation (must be MT-safe)
- static void* malloc (size_t size);
- static void* realloc (void *memblock, size_t size);
- static void free (void *memblock);
+ static void* malloc (size_t size, MEMFLAGS flags, address caller_pc = 0);
+ static void* realloc (void *memblock, size_t size, MEMFLAGS flags, address caller_pc = 0);
+ static void free (void *memblock, MEMFLAGS flags = mtNone);
static bool check_heap(bool force = false); // verify C heap integrity
- static char* strdup(const char *); // Like strdup
+ static char* strdup(const char *, MEMFLAGS flags = mtInternal); // Like strdup
#ifndef PRODUCT
static julong num_mallocs; // # of calls to malloc/realloc
@@ -640,6 +665,10 @@
// On Windows this will create an actual minidump, on Linux/Solaris it will simply check core dump limits
static void check_or_create_dump(void* exceptionRecord, void* contextRecord, char* buffer, size_t bufferSize);
+ // Get the default path to the core file
+ // Returns the length of the string
+ static int get_core_path(char* buffer, size_t bufferSize);
+
// JVMTI & JVM monitoring and management support
// The thread_cpu_time() and current_thread_cpu_time() are only
// supported if is_thread_cpu_time_supported() returns true.
--- a/hotspot/src/share/vm/runtime/osThread.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/osThread.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -58,7 +58,7 @@
// the main thread into its own Thread at will.
-class OSThread: public CHeapObj {
+class OSThread: public CHeapObj<mtThread> {
friend class VMStructs;
private:
OSThreadStartFunc _start_proc; // Thread start routine
--- a/hotspot/src/share/vm/runtime/park.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/park.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -141,7 +141,7 @@
// although Niagara's hash function should help.
void * ParkEvent::operator new (size_t sz) {
- return (void *) ((intptr_t (CHeapObj::operator new (sz + 256)) + 256) & -256) ;
+ return (void *) ((intptr_t (AllocateHeap(sz + 256, mtInternal, CALLER_PC)) + 256) & -256) ;
}
void ParkEvent::operator delete (void * a) {
--- a/hotspot/src/share/vm/runtime/perfData.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/perfData.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -81,7 +81,7 @@
const char* prefix = PerfDataManager::ns_to_string(ns);
- _name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2);
+ _name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2, mtInternal);
assert(_name != NULL && strlen(name) != 0, "invalid name");
if (ns == NULL_NS) {
@@ -111,10 +111,10 @@
PerfData::~PerfData() {
if (_name != NULL) {
- FREE_C_HEAP_ARRAY(char, _name);
+ FREE_C_HEAP_ARRAY(char, _name, mtInternal);
}
if (is_on_c_heap()) {
- FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep);
+ FREE_C_HEAP_ARRAY(PerfDataEntry, _pdep, mtInternal);
}
}
@@ -137,7 +137,7 @@
if (psmp == NULL) {
// out of PerfMemory memory resources. allocate on the C heap
// to avoid vm termination.
- psmp = NEW_C_HEAP_ARRAY(char, size);
+ psmp = NEW_C_HEAP_ARRAY(char, size, mtInternal);
_on_c_heap = true;
}
@@ -559,12 +559,12 @@
PerfDataList::PerfDataList(int length) {
- _set = new(ResourceObj::C_HEAP) PerfDataArray(length, true);
+ _set = new(ResourceObj::C_HEAP, mtInternal) PerfDataArray(length, true);
}
PerfDataList::PerfDataList(PerfDataList* p) {
- _set = new(ResourceObj::C_HEAP) PerfDataArray(p->length(), true);
+ _set = new(ResourceObj::C_HEAP, mtInternal) PerfDataArray(p->length(), true);
_set->appendAll(p->get_impl());
}
--- a/hotspot/src/share/vm/runtime/perfData.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/perfData.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -240,7 +240,7 @@
* be removed from the product in the future.
*
*/
-class PerfData : public CHeapObj {
+class PerfData : public CHeapObj<mtInternal> {
friend class StatSampler; // for access to protected void sample()
friend class PerfDataManager; // for access to protected destructor
@@ -342,7 +342,7 @@
* invoke the take_sample() method and write the value returned to its
* appropriate location in the PerfData memory region.
*/
-class PerfLongSampleHelper : public CHeapObj {
+class PerfLongSampleHelper : public CHeapObj<mtInternal> {
public:
virtual jlong take_sample() = 0;
};
@@ -591,7 +591,7 @@
* some other implementation, as long as that implementation provides
* a mechanism to iterate over the container by index.
*/
-class PerfDataList : public CHeapObj {
+class PerfDataList : public CHeapObj<mtInternal> {
private:
--- a/hotspot/src/share/vm/runtime/perfMemory.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/perfMemory.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -112,7 +112,7 @@
warning("Could not create PerfData Memory region, reverting to malloc");
}
- _prologue = NEW_C_HEAP_OBJ(PerfDataPrologue);
+ _prologue = NEW_C_HEAP_OBJ(PerfDataPrologue, mtInternal);
}
else {
@@ -244,10 +244,10 @@
if (PerfDataSaveFile != NULL) {
// dest_file_name stores the validated file name if file_name
// contains %p which will be replaced by pid.
- dest_file = NEW_C_HEAP_ARRAY(char, JVM_MAXPATHLEN);
+ dest_file = NEW_C_HEAP_ARRAY(char, JVM_MAXPATHLEN, mtInternal);
if(!Arguments::copy_expand_pid(PerfDataSaveFile, strlen(PerfDataSaveFile),
dest_file, JVM_MAXPATHLEN)) {
- FREE_C_HEAP_ARRAY(char, dest_file);
+ FREE_C_HEAP_ARRAY(char, dest_file, mtInternal);
if (PrintMiscellaneous && Verbose) {
warning("Invalid performance data file path name specified, "\
"fall back to a default name");
@@ -257,7 +257,7 @@
}
}
// create the name of the file for retaining the instrumentation memory.
- dest_file = NEW_C_HEAP_ARRAY(char, PERFDATA_FILENAME_LEN);
+ dest_file = NEW_C_HEAP_ARRAY(char, PERFDATA_FILENAME_LEN, mtInternal);
jio_snprintf(dest_file, PERFDATA_FILENAME_LEN,
"%s_%d", PERFDATA_NAME, os::current_process_id());
--- a/hotspot/src/share/vm/runtime/reflectionUtils.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/reflectionUtils.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -59,7 +59,7 @@
GrowableArray<FilteredField*> *FilteredFieldsMap::_filtered_fields =
- new (ResourceObj::C_HEAP) GrowableArray<FilteredField*>(3,true);
+ new (ResourceObj::C_HEAP, mtInternal) GrowableArray<FilteredField*>(3,true);
void FilteredFieldsMap::initialize() {
--- a/hotspot/src/share/vm/runtime/safepoint.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -48,6 +48,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/sweeper.hpp"
#include "runtime/synchronizer.hpp"
+#include "services/memTracker.hpp"
#include "services/runtimeService.hpp"
#include "utilities/events.hpp"
#ifdef TARGET_ARCH_x86
@@ -546,6 +547,10 @@
if (UseGCLogFileRotation) {
gclog_or_tty->rotate_log();
}
+
+ if (MemTracker::is_on()) {
+ MemTracker::sync();
+ }
}
@@ -1157,7 +1162,7 @@
stats_array_size = PrintSafepointStatisticsCount;
}
_safepoint_stats = (SafepointStats*)os::malloc(stats_array_size
- * sizeof(SafepointStats));
+ * sizeof(SafepointStats), mtInternal);
guarantee(_safepoint_stats != NULL,
"not enough memory for safepoint instrumentation data");
--- a/hotspot/src/share/vm/runtime/safepoint.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/safepoint.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -190,7 +190,7 @@
};
// State class for a thread suspended at a safepoint
-class ThreadSafepointState: public CHeapObj {
+class ThreadSafepointState: public CHeapObj<mtInternal> {
public:
// These states are maintained by VM thread while threads are being brought
// to a safepoint. After SafepointSynchronize::end(), they are reset to
--- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -2117,7 +2117,7 @@
// A simple wrapper class around the calling convention information
// that allows sharing of adapters for the same calling convention.
-class AdapterFingerPrint : public CHeapObj {
+class AdapterFingerPrint : public CHeapObj<mtCode> {
private:
union {
int _compact[3];
@@ -2174,7 +2174,7 @@
ptr = _value._compact;
} else {
_length = len;
- _value._fingerprint = NEW_C_HEAP_ARRAY(int, _length);
+ _value._fingerprint = NEW_C_HEAP_ARRAY(int, _length, mtCode);
ptr = _value._fingerprint;
}
@@ -2193,7 +2193,7 @@
~AdapterFingerPrint() {
if (_length > 0) {
- FREE_C_HEAP_ARRAY(int, _value._fingerprint);
+ FREE_C_HEAP_ARRAY(int, _value._fingerprint, mtCode);
}
}
@@ -2251,7 +2251,7 @@
// A hashtable mapping from AdapterFingerPrints to AdapterHandlerEntries
-class AdapterHandlerTable : public BasicHashtable {
+class AdapterHandlerTable : public BasicHashtable<mtCode> {
friend class AdapterHandlerTableIterator;
private:
@@ -2265,16 +2265,16 @@
#endif
AdapterHandlerEntry* bucket(int i) {
- return (AdapterHandlerEntry*)BasicHashtable::bucket(i);
+ return (AdapterHandlerEntry*)BasicHashtable<mtCode>::bucket(i);
}
public:
AdapterHandlerTable()
- : BasicHashtable(293, sizeof(AdapterHandlerEntry)) { }
+ : BasicHashtable<mtCode>(293, sizeof(AdapterHandlerEntry)) { }
// Create a new entry suitable for insertion in the table
AdapterHandlerEntry* new_entry(AdapterFingerPrint* fingerprint, address i2c_entry, address c2i_entry, address c2i_unverified_entry) {
- AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable::new_entry(fingerprint->compute_hash());
+ AdapterHandlerEntry* entry = (AdapterHandlerEntry*)BasicHashtable<mtCode>::new_entry(fingerprint->compute_hash());
entry->init(fingerprint, i2c_entry, c2i_entry, c2i_unverified_entry);
return entry;
}
@@ -2287,7 +2287,7 @@
void free_entry(AdapterHandlerEntry* entry) {
entry->deallocate();
- BasicHashtable::free_entry(entry);
+ BasicHashtable<mtCode>::free_entry(entry);
}
// Find a entry with the same fingerprint if it exists
@@ -2572,8 +2572,8 @@
void AdapterHandlerEntry::deallocate() {
delete _fingerprint;
#ifdef ASSERT
- if (_saved_code) FREE_C_HEAP_ARRAY(unsigned char, _saved_code);
- if (_saved_sig) FREE_C_HEAP_ARRAY(Basictype, _saved_sig);
+ if (_saved_code) FREE_C_HEAP_ARRAY(unsigned char, _saved_code, mtCode);
+ if (_saved_sig) FREE_C_HEAP_ARRAY(Basictype, _saved_sig, mtCode);
#endif
}
@@ -2583,11 +2583,11 @@
// against other versions. If the code is captured after relocation
// then relative instructions won't be equivalent.
void AdapterHandlerEntry::save_code(unsigned char* buffer, int length, int total_args_passed, BasicType* sig_bt) {
- _saved_code = NEW_C_HEAP_ARRAY(unsigned char, length);
+ _saved_code = NEW_C_HEAP_ARRAY(unsigned char, length, mtCode);
_code_length = length;
memcpy(_saved_code, buffer, length);
_total_args_passed = total_args_passed;
- _saved_sig = NEW_C_HEAP_ARRAY(BasicType, _total_args_passed);
+ _saved_sig = NEW_C_HEAP_ARRAY(BasicType, _total_args_passed, mtCode);
memcpy(_saved_sig, sig_bt, _total_args_passed * sizeof(BasicType));
}
@@ -2893,7 +2893,7 @@
int max_locals = moop->max_locals();
// Allocate temp buffer, 1 word per local & 2 per active monitor
int buf_size_words = max_locals + active_monitor_count*2;
- intptr_t *buf = NEW_C_HEAP_ARRAY(intptr_t,buf_size_words);
+ intptr_t *buf = NEW_C_HEAP_ARRAY(intptr_t,buf_size_words, mtCode);
// Copy the locals. Order is preserved so that loading of longs works.
// Since there's no GC I can copy the oops blindly.
@@ -2923,7 +2923,7 @@
JRT_END
JRT_LEAF(void, SharedRuntime::OSR_migration_end( intptr_t* buf) )
- FREE_C_HEAP_ARRAY(intptr_t,buf);
+ FREE_C_HEAP_ARRAY(intptr_t,buf, mtCode);
JRT_END
bool AdapterHandlerLibrary::contains(CodeBlob* b) {
--- a/hotspot/src/share/vm/runtime/sharedRuntime.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/sharedRuntime.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -610,7 +610,7 @@
// used by the adapters. The code generation happens here because it's very
// similar to what the adapters have to do.
-class AdapterHandlerEntry : public BasicHashtableEntry {
+class AdapterHandlerEntry : public BasicHashtableEntry<mtCode> {
friend class AdapterHandlerTable;
private:
@@ -656,7 +656,7 @@
AdapterFingerPrint* fingerprint() { return _fingerprint; }
AdapterHandlerEntry* next() {
- return (AdapterHandlerEntry*)BasicHashtableEntry::next();
+ return (AdapterHandlerEntry*)BasicHashtableEntry<mtCode>::next();
}
#ifdef ASSERT
--- a/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/stubCodeGenerator.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -36,7 +36,7 @@
// Currently, code descriptors are simply chained in a linked list,
// this may have to change if searching becomes too slow.
-class StubCodeDesc: public CHeapObj {
+class StubCodeDesc: public CHeapObj<mtCode> {
protected:
static StubCodeDesc* _list; // the list of all descriptors
static int _count; // length of list
--- a/hotspot/src/share/vm/runtime/sweeper.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -228,7 +228,7 @@
#ifdef ASSERT
if (LogSweeper && _records == NULL) {
// Create the ring buffer for the logging code
- _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries);
+ _records = NEW_C_HEAP_ARRAY(SweeperRecord, SweeperLogEntries, mtGC);
memset(_records, 0, sizeof(SweeperRecord) * SweeperLogEntries);
}
#endif
--- a/hotspot/src/share/vm/runtime/task.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/task.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
// ...
// pf.disenroll();
-class PeriodicTask: public CHeapObj {
+class PeriodicTask: public CHeapObj<mtInternal> {
public:
// Useful constants.
// The interval constants are used to ensure the declared interval
--- a/hotspot/src/share/vm/runtime/thread.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/thread.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -73,6 +73,7 @@
#include "runtime/vm_operations.hpp"
#include "services/attachListener.hpp"
#include "services/management.hpp"
+#include "services/memTracker.hpp"
#include "services/threadService.hpp"
#include "trace/traceEventTypes.hpp"
#include "utilities/defaultStream.hpp"
@@ -159,6 +160,7 @@
#endif // ndef DTRACE_ENABLED
+
// Class hierarchy
// - Thread
// - VMThread
@@ -168,13 +170,13 @@
// - CompilerThread
// ======= Thread ========
-
// Support for forcing alignment of thread objects for biased locking
-void* Thread::operator new(size_t size) {
+void* Thread::allocate(size_t size, bool throw_excpt, MEMFLAGS flags) {
if (UseBiasedLocking) {
const int alignment = markOopDesc::biased_lock_alignment;
size_t aligned_size = size + (alignment - sizeof(intptr_t));
- void* real_malloc_addr = CHeapObj::operator new(aligned_size);
+ void* real_malloc_addr = throw_excpt? AllocateHeap(aligned_size, flags, CURRENT_PC)
+ : os::malloc(aligned_size, flags, CURRENT_PC);
void* aligned_addr = (void*) align_size_up((intptr_t) real_malloc_addr, alignment);
assert(((uintptr_t) aligned_addr + (uintptr_t) size) <=
((uintptr_t) real_malloc_addr + (uintptr_t) aligned_size),
@@ -187,16 +189,17 @@
((Thread*) aligned_addr)->_real_malloc_address = real_malloc_addr;
return aligned_addr;
} else {
- return CHeapObj::operator new(size);
+ return throw_excpt? AllocateHeap(size, flags, CURRENT_PC)
+ : os::malloc(size, flags, CURRENT_PC);
}
}
void Thread::operator delete(void* p) {
if (UseBiasedLocking) {
void* real_malloc_addr = ((Thread*) p)->_real_malloc_address;
- CHeapObj::operator delete(real_malloc_addr);
+ FreeHeap(real_malloc_addr, mtThread);
} else {
- CHeapObj::operator delete(p);
+ FreeHeap(p, mtThread);
}
}
@@ -214,8 +217,8 @@
// allocated data structures
set_osthread(NULL);
- set_resource_area(new ResourceArea());
- set_handle_area(new HandleArea(NULL));
+ set_resource_area(new (mtThread)ResourceArea());
+ set_handle_area(new (mtThread) HandleArea(NULL));
set_active_handles(NULL);
set_free_handle_block(NULL);
set_last_handle_mark(NULL);
@@ -306,12 +309,17 @@
// set up any platform-specific state.
os::initialize_thread();
-
}
void Thread::record_stack_base_and_size() {
set_stack_base(os::current_stack_base());
set_stack_size(os::current_stack_size());
+
+ // record thread's native stack, stack grows downward
+ address vm_base = _stack_base - _stack_size;
+ MemTracker::record_virtual_memory_reserve(vm_base, _stack_size,
+ CURRENT_PC, this);
+ MemTracker::record_virtual_memory_type(vm_base, mtThreadStack);
}
@@ -319,6 +327,9 @@
// Reclaim the objectmonitors from the omFreeList of the moribund thread.
ObjectSynchronizer::omFlush (this) ;
+ MemTracker::record_virtual_memory_release((_stack_base - _stack_size),
+ _stack_size, this);
+
// deallocate data structures
delete resource_area();
// since the handle marks are using the handle area, we have to deallocated the root
@@ -1128,14 +1139,14 @@
NamedThread::~NamedThread() {
if (_name != NULL) {
- FREE_C_HEAP_ARRAY(char, _name);
+ FREE_C_HEAP_ARRAY(char, _name, mtThread);
_name = NULL;
}
}
void NamedThread::set_name(const char* format, ...) {
guarantee(_name == NULL, "Only get to set name once.");
- _name = NEW_C_HEAP_ARRAY(char, max_name_len);
+ _name = NEW_C_HEAP_ARRAY(char, max_name_len, mtThread);
guarantee(_name != NULL, "alloc failure");
va_list ap;
va_start(ap, format);
@@ -1318,6 +1329,7 @@
set_monitor_chunks(NULL);
set_next(NULL);
set_thread_state(_thread_new);
+ set_recorder(NULL);
_terminated = _not_terminated;
_privileged_stack_top = NULL;
_array_for_gc = NULL;
@@ -1393,6 +1405,7 @@
_jni_attach_state = _not_attaching_via_jni;
}
assert(_deferred_card_mark.is_empty(), "Default MemRegion ctor");
+ _safepoint_visible = false;
}
bool JavaThread::reguard_stack(address cur_sp) {
@@ -1455,7 +1468,7 @@
thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :
os::java_thread;
os::create_thread(this, thr_type, stack_sz);
-
+ _safepoint_visible = false;
// The _osthread may be NULL here because we ran out of memory (too many threads active).
// We need to throw and OutOfMemoryError - however we cannot do this here because the caller
// may hold a lock and all locks must be unlocked before throwing the exception (throwing
@@ -1473,6 +1486,11 @@
tty->print_cr("terminate thread %p", this);
}
+ // Info NMT that this JavaThread is exiting, its memory
+ // recorder should be collected
+ assert(!is_safepoint_visible(), "wrong state");
+ MemTracker::thread_exiting(this);
+
// JSR166 -- return the parker to the free list
Parker::Release(_parker);
_parker = NULL ;
@@ -2915,7 +2933,7 @@
void JavaThread::popframe_preserve_args(ByteSize size_in_bytes, void* start) {
assert(_popframe_preserved_args == NULL, "should not wipe out old PopFrame preserved arguments");
if (in_bytes(size_in_bytes) != 0) {
- _popframe_preserved_args = NEW_C_HEAP_ARRAY(char, in_bytes(size_in_bytes));
+ _popframe_preserved_args = NEW_C_HEAP_ARRAY(char, in_bytes(size_in_bytes), mtThread);
_popframe_preserved_args_size = in_bytes(size_in_bytes);
Copy::conjoint_jbytes(start, _popframe_preserved_args, _popframe_preserved_args_size);
}
@@ -2937,7 +2955,7 @@
void JavaThread::popframe_free_preserved_args() {
assert(_popframe_preserved_args != NULL, "should not free PopFrame preserved arguments twice");
- FREE_C_HEAP_ARRAY(char, (char*) _popframe_preserved_args);
+ FREE_C_HEAP_ARRAY(char, (char*) _popframe_preserved_args, mtThread);
_popframe_preserved_args = NULL;
_popframe_preserved_args_size = 0;
}
@@ -3186,6 +3204,14 @@
jint os_init_2_result = os::init_2();
if (os_init_2_result != JNI_OK) return os_init_2_result;
+ // intialize TLS
+ ThreadLocalStorage::init();
+
+ // Bootstrap native memory tracking, so it can start recording memory
+ // activities before worker thread is started. This is the first phase
+ // of bootstrapping, VM is currently running in single-thread mode.
+ MemTracker::bootstrap_single_thread();
+
// Initialize output stream logging
ostream_init_log();
@@ -3205,9 +3231,6 @@
_number_of_threads = 0;
_number_of_non_daemon_threads = 0;
- // Initialize TLS
- ThreadLocalStorage::init();
-
// Initialize global data structures and create system classes in heap
vm_init_globals();
@@ -3239,6 +3262,9 @@
// Initialize Java-Level synchronization subsystem
ObjectMonitor::Initialize() ;
+ // Second phase of bootstrapping, VM is about entering multi-thread mode
+ MemTracker::bootstrap_multi_thread();
+
// Initialize global modules
jint status = init_globals();
if (status != JNI_OK) {
@@ -3266,6 +3292,9 @@
Universe::verify(); // make sure we're starting with a clean slate
}
+ // Fully start NMT
+ MemTracker::start();
+
// Create the VMThread
{ TraceTime timer("Start VMThread", TraceStartupTime);
VMThread::create();
@@ -3570,11 +3599,11 @@
if (library == NULL) {
const char *sub_msg = " in absolute path, with error: ";
size_t len = strlen(msg) + strlen(name) + strlen(sub_msg) + strlen(ebuf) + 1;
- char *buf = NEW_C_HEAP_ARRAY(char, len);
+ char *buf = NEW_C_HEAP_ARRAY(char, len, mtThread);
jio_snprintf(buf, len, "%s%s%s%s", msg, name, sub_msg, ebuf);
// If we can't find the agent, exit.
vm_exit_during_initialization(buf, NULL);
- FREE_C_HEAP_ARRAY(char, buf);
+ FREE_C_HEAP_ARRAY(char, buf, mtThread);
}
} else {
// Try to load the agent from the standard dll directory
@@ -3588,7 +3617,7 @@
const char *fmt = "%s/bin/java %s -Dkernel.background.download=false"
" sun.jkernel.DownloadManager -download client_jvm";
size_t length = strlen(props) + strlen(home) + strlen(fmt) + 1;
- char *cmd = NEW_C_HEAP_ARRAY(char, length);
+ char *cmd = NEW_C_HEAP_ARRAY(char, length, mtThread);
jio_snprintf(cmd, length, fmt, home, props);
int status = os::fork_and_exec(cmd);
FreeHeap(props);
@@ -3597,7 +3626,7 @@
vm_exit_during_initialization("fork_and_exec failed: %s",
strerror(errno));
}
- FREE_C_HEAP_ARRAY(char, cmd);
+ FREE_C_HEAP_ARRAY(char, cmd, mtThread);
// when this comes back the instrument.dll should be where it belongs.
library = os::dll_load(buffer, ebuf, sizeof ebuf);
}
@@ -3609,11 +3638,11 @@
if (library == NULL) {
const char *sub_msg = " on the library path, with error: ";
size_t len = strlen(msg) + strlen(name) + strlen(sub_msg) + strlen(ebuf) + 1;
- char *buf = NEW_C_HEAP_ARRAY(char, len);
+ char *buf = NEW_C_HEAP_ARRAY(char, len, mtThread);
jio_snprintf(buf, len, "%s%s%s%s", msg, name, sub_msg, ebuf);
// If we can't find the agent, exit.
vm_exit_during_initialization(buf, NULL);
- FREE_C_HEAP_ARRAY(char, buf);
+ FREE_C_HEAP_ARRAY(char, buf, mtThread);
}
}
}
@@ -3782,6 +3811,7 @@
// and VM_Exit op at VM level.
//
// Shutdown sequence:
+// + Shutdown native memory tracking if it is on
// + Wait until we are the last non-daemon thread to execute
// <-- every thing is still working at this moment -->
// + Call java.lang.Shutdown.shutdown(), which will invoke Java level
@@ -3827,6 +3857,10 @@
Mutex::_as_suspend_equivalent_flag);
}
+ // Shutdown NMT before exit. Otherwise,
+ // it will run into trouble when system destroys static variables.
+ MemTracker::shutdown(MemTracker::NMT_normal);
+
// Hang forever on exit if we are reporting an error.
if (ShowMessageBoxOnError && is_error_reported()) {
os::infinite_sleep();
@@ -3933,6 +3967,8 @@
daemon = false;
}
+ p->set_safepoint_visible(true);
+
ThreadService::add_thread(p, daemon);
// Possible GC point.
@@ -3978,6 +4014,10 @@
// to do callbacks into the safepoint code. However, the safepoint code is not aware
// of this thread since it is removed from the queue.
p->set_terminated_value();
+
+ // Now, this thread is not visible to safepoint
+ p->set_safepoint_visible(false);
+
} // unlock Threads_lock
// Since Events::log uses a lock, we grab it outside the Threads_lock
--- a/hotspot/src/share/vm/runtime/thread.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/thread.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -41,6 +41,7 @@
#include "runtime/stubRoutines.hpp"
#include "runtime/threadLocalStorage.hpp"
#include "runtime/unhandledOops.hpp"
+#include "services/memRecorder.hpp"
#include "trace/tracing.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/top.hpp"
@@ -100,12 +101,16 @@
//oop _pending_exception; // pending exception for current thread
// const char* _exception_file; // file information for exception (debugging only)
// int _exception_line; // line information for exception (debugging only)
-
+ protected:
// Support for forcing alignment of thread objects for biased locking
void* _real_malloc_address;
public:
- void* operator new(size_t size);
+ void* operator new(size_t size) { return allocate(size, true); }
+ void* operator new(size_t size, std::nothrow_t& nothrow_constant) { return allocate(size, false); }
void operator delete(void* p);
+
+ protected:
+ static void* allocate(size_t size, bool throw_excpt, MEMFLAGS flags = mtThread);
private:
// ***************************************************************
@@ -548,7 +553,6 @@
virtual void print_on_error(outputStream* st, char* buf, int buflen) const;
// Debug-only code
-
#ifdef ASSERT
private:
// Deadlock detection support for Mutex locks. List of locks own by thread.
@@ -1027,9 +1031,15 @@
bool do_not_unlock_if_synchronized() { return _do_not_unlock_if_synchronized; }
void set_do_not_unlock_if_synchronized(bool val) { _do_not_unlock_if_synchronized = val; }
+ // native memory tracking
+ inline MemRecorder* get_recorder() const { return (MemRecorder*)_recorder; }
+ inline void set_recorder(MemRecorder* rc) { _recorder = (volatile MemRecorder*)rc; }
+
+ private:
+ // per-thread memory recorder
+ volatile MemRecorder* _recorder;
// Suspend/resume support for JavaThread
-
private:
void set_ext_suspended() { set_suspend_flag (_ext_suspended); }
void clear_ext_suspended() { clear_suspend_flag(_ext_suspended); }
@@ -1453,6 +1463,18 @@
return result;
}
+ // NMT (Native memory tracking) support.
+ // This flag helps NMT to determine if this JavaThread will be blocked
+ // at safepoint. If not, ThreadCritical is needed for writing memory records.
+ // JavaThread is only safepoint visible when it is in Threads' thread list,
+ // it is not visible until it is added to the list and becomes invisible
+ // once it is removed from the list.
+ public:
+ bool is_safepoint_visible() const { return _safepoint_visible; }
+ void set_safepoint_visible(bool visible) { _safepoint_visible = visible; }
+ private:
+ bool _safepoint_visible;
+
// Static operations
public:
// Returns the running thread as a JavaThread
--- a/hotspot/src/share/vm/runtime/unhandledOops.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/unhandledOops.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -37,7 +37,7 @@
UnhandledOops::UnhandledOops(Thread* thread) {
_thread = thread;
- _oop_list = new (ResourceObj::C_HEAP)
+ _oop_list = new (ResourceObj::C_HEAP, mtInternal)
GrowableArray<UnhandledOopEntry>(free_list_size, true);
_level = 0;
}
--- a/hotspot/src/share/vm/runtime/vframeArray.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/vframeArray.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -443,7 +443,7 @@
// Allocate the vframeArray
vframeArray * result = (vframeArray*) AllocateHeap(sizeof(vframeArray) + // fixed part
sizeof(vframeArrayElement) * (chunk->length() - 1), // variable part
- "vframeArray::allocate");
+ mtCompiler);
result->_frames = chunk->length();
result->_owner_thread = thread;
result->_sender = sender;
--- a/hotspot/src/share/vm/runtime/vframeArray.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/vframeArray.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -108,7 +108,7 @@
// but it does make debugging easier even if we can't look
// at the data in each vframeElement
-class vframeArray: public CHeapObj {
+class vframeArray: public CHeapObj<mtCompiler> {
friend class VMStructs;
private:
--- a/hotspot/src/share/vm/runtime/vframe_hp.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/vframe_hp.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -154,7 +154,7 @@
} else {
// No deferred updates pending for this thread.
// allocate in C heap
- deferred = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true);
+ deferred = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariableSet*> (1, true);
thread()->set_deferred_locals(deferred);
}
deferred->push(new jvmtiDeferredLocalVariableSet(method(), bci(), fr().id()));
@@ -323,7 +323,7 @@
_bci = bci;
_id = id;
// Alway will need at least one, must be on C heap
- _locals = new(ResourceObj::C_HEAP) GrowableArray<jvmtiDeferredLocalVariable*> (1, true);
+ _locals = new(ResourceObj::C_HEAP, mtCompiler) GrowableArray<jvmtiDeferredLocalVariable*> (1, true);
}
jvmtiDeferredLocalVariableSet::~jvmtiDeferredLocalVariableSet() {
--- a/hotspot/src/share/vm/runtime/vframe_hp.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/vframe_hp.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -89,7 +89,7 @@
// any updated locals.
class jvmtiDeferredLocalVariable;
-class jvmtiDeferredLocalVariableSet : public CHeapObj {
+class jvmtiDeferredLocalVariableSet : public CHeapObj<mtCompiler> {
private:
methodOop _method; // must be GC'd
@@ -119,7 +119,7 @@
};
-class jvmtiDeferredLocalVariable : public CHeapObj {
+class jvmtiDeferredLocalVariable : public CHeapObj<mtCompiler> {
public:
jvmtiDeferredLocalVariable(int index, BasicType type, jvalue value);
--- a/hotspot/src/share/vm/runtime/virtualspace.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/virtualspace.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -26,6 +26,7 @@
#include "oops/markOop.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/virtualspace.hpp"
+#include "services/memTracker.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
@@ -489,6 +490,10 @@
(UseCompressedOops && (Universe::narrow_oop_base() != NULL) &&
Universe::narrow_oop_use_implicit_null_checks()) ?
lcm(os::vm_page_size(), alignment) : 0) {
+ if (base() > 0) {
+ MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap);
+ }
+
// Only reserved space for the java heap should have a noaccess_prefix
// if using compressed oops.
protect_noaccess_prefix(size);
@@ -504,6 +509,10 @@
(UseCompressedOops && (Universe::narrow_oop_base() != NULL) &&
Universe::narrow_oop_use_implicit_null_checks()) ?
lcm(os::vm_page_size(), prefix_align) : 0) {
+ if (base() > 0) {
+ MemTracker::record_virtual_memory_type((address)base(), mtJavaHeap);
+ }
+
protect_noaccess_prefix(prefix_size+suffix_size);
}
@@ -513,6 +522,7 @@
size_t rs_align,
bool large) :
ReservedSpace(r_size, rs_align, large, /*executable*/ true) {
+ MemTracker::record_virtual_memory_type((address)base(), mtCode);
}
// VirtualSpace
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -235,7 +235,6 @@
#ifndef REG_COUNT
#define REG_COUNT 0
#endif
-
// whole purpose of this function is to work around bug c++/27724 in gcc 4.1.1
// with optimization turned on it doesn't affect produced code
static inline uint64_t cast_uint64_t(size_t x)
@@ -244,6 +243,16 @@
}
+typedef HashtableEntry<intptr_t, mtInternal> IntptrHashtableEntry;
+typedef Hashtable<intptr_t, mtInternal> IntptrHashtable;
+typedef Hashtable<Symbol*, mtSymbol> SymbolHashtable;
+typedef HashtableEntry<Symbol*, mtClass> SymbolHashtableEntry;
+typedef Hashtable<oop, mtSymbol> StringHashtable;
+typedef TwoOopHashtable<klassOop, mtClass> klassOopTwoOopHashtable;
+typedef Hashtable<klassOop, mtClass> klassOopHashtable;
+typedef HashtableEntry<klassOop, mtClass> klassHashtableEntry;
+typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
+
//--------------------------------------------------------------------------------
// VM_STRUCTS
//
@@ -299,7 +308,7 @@
nonstatic_field(instanceKlass, _protection_domain, oop) \
nonstatic_field(instanceKlass, _signers, objArrayOop) \
nonstatic_field(instanceKlass, _source_file_name, Symbol*) \
- nonstatic_field(instanceKlass, _source_debug_extension, Symbol*) \
+ nonstatic_field(instanceKlass, _source_debug_extension, char*) \
nonstatic_field(instanceKlass, _inner_classes, typeArrayOop) \
nonstatic_field(instanceKlass, _nonstatic_field_size, int) \
nonstatic_field(instanceKlass, _static_field_size, int) \
@@ -711,26 +720,26 @@
/* HashtableBucket */ \
/*******************/ \
\
- nonstatic_field(HashtableBucket, _entry, BasicHashtableEntry*) \
+ nonstatic_field(HashtableBucket<mtInternal>, _entry, BasicHashtableEntry<mtInternal>*) \
\
/******************/ \
/* HashtableEntry */ \
/******************/ \
\
- nonstatic_field(BasicHashtableEntry, _next, BasicHashtableEntry*) \
- nonstatic_field(BasicHashtableEntry, _hash, unsigned int) \
- nonstatic_field(HashtableEntry<intptr_t>, _literal, intptr_t) \
+ nonstatic_field(BasicHashtableEntry<mtInternal>, _next, BasicHashtableEntry<mtInternal>*) \
+ nonstatic_field(BasicHashtableEntry<mtInternal>, _hash, unsigned int) \
+ nonstatic_field(IntptrHashtableEntry, _literal, intptr_t) \
\
/*************/ \
/* Hashtable */ \
/*************/ \
\
- nonstatic_field(BasicHashtable, _table_size, int) \
- nonstatic_field(BasicHashtable, _buckets, HashtableBucket*) \
- nonstatic_field(BasicHashtable, _free_list, BasicHashtableEntry*) \
- nonstatic_field(BasicHashtable, _first_free_entry, char*) \
- nonstatic_field(BasicHashtable, _end_block, char*) \
- nonstatic_field(BasicHashtable, _entry_size, int) \
+ nonstatic_field(BasicHashtable<mtInternal>, _table_size, int) \
+ nonstatic_field(BasicHashtable<mtInternal>, _buckets, HashtableBucket<mtInternal>*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _free_list, BasicHashtableEntry<mtInternal>*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _first_free_entry, char*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _end_block, char*) \
+ nonstatic_field(BasicHashtable<mtInternal>, _entry_size, int) \
\
/*******************/ \
/* DictionaryEntry */ \
@@ -1538,20 +1547,20 @@
/* SymbolTable, SystemDictionary */ \
/*********************************/ \
\
- declare_toplevel_type(BasicHashtable) \
- declare_type(Hashtable<intptr_t>, BasicHashtable) \
- declare_type(SymbolTable, Hashtable<Symbol*>) \
- declare_type(StringTable, Hashtable<oop>) \
- declare_type(LoaderConstraintTable, Hashtable<klassOop>) \
- declare_type(TwoOopHashtable<klassOop>, Hashtable<klassOop>) \
- declare_type(Dictionary, TwoOopHashtable<klassOop>) \
- declare_type(PlaceholderTable, TwoOopHashtable<Symbol*>) \
- declare_toplevel_type(BasicHashtableEntry) \
- declare_type(HashtableEntry<intptr_t>, BasicHashtableEntry) \
- declare_type(DictionaryEntry, HashtableEntry<klassOop>) \
- declare_type(PlaceholderEntry, HashtableEntry<Symbol*>) \
- declare_type(LoaderConstraintEntry, HashtableEntry<klassOop>) \
- declare_toplevel_type(HashtableBucket) \
+ declare_toplevel_type(BasicHashtable<mtInternal>) \
+ declare_type(IntptrHashtable, BasicHashtable<mtInternal>) \
+ declare_type(SymbolTable, SymbolHashtable) \
+ declare_type(StringTable, StringHashtable) \
+ declare_type(LoaderConstraintTable, klassOopHashtable) \
+ declare_type(klassOopTwoOopHashtable, klassOopHashtable) \
+ declare_type(Dictionary, klassOopTwoOopHashtable) \
+ declare_type(PlaceholderTable, SymbolTwoOopHashtable) \
+ declare_toplevel_type(BasicHashtableEntry<mtInternal>) \
+ declare_type(IntptrHashtableEntry, BasicHashtableEntry<mtInternal>) \
+ declare_type(DictionaryEntry, klassHashtableEntry) \
+ declare_type(PlaceholderEntry, SymbolHashtableEntry) \
+ declare_type(LoaderConstraintEntry, klassHashtableEntry) \
+ declare_toplevel_type(HashtableBucket<mtInternal>) \
declare_toplevel_type(SystemDictionary) \
declare_toplevel_type(vmSymbols) \
declare_toplevel_type(ProtectionDomainEntry) \
--- a/hotspot/src/share/vm/runtime/vmThread.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/vmThread.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -46,7 +46,7 @@
// Encapsulates both queue management and
// and priority policy
//
-class VMOperationQueue : public CHeapObj {
+class VMOperationQueue : public CHeapObj<mtInternal> {
private:
enum Priorities {
SafepointPriority, // Highest priority (operation executed at a safepoint)
--- a/hotspot/src/share/vm/runtime/vm_operations.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/runtime/vm_operations.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -96,7 +96,7 @@
template(JFRCheckpoint) \
template(Exit) \
-class VM_Operation: public CHeapObj {
+class VM_Operation: public CHeapObj<mtInternal> {
public:
enum Mode {
_safepoint, // blocking, safepoint, vm_op C-heap allocated
--- a/hotspot/src/share/vm/services/attachListener.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/attachListener.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -320,7 +320,7 @@
}
bool res = CommandLineFlags::ccstrAtPut((char*)name, &value, ATTACH_ON_DEMAND);
if (res) {
- FREE_C_HEAP_ARRAY(char, value);
+ FREE_C_HEAP_ARRAY(char, value, mtInternal);
} else {
out->print_cr("setting flag %s failed", name);
}
--- a/hotspot/src/share/vm/services/attachListener.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/attachListener.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -98,7 +98,7 @@
};
#ifndef SERVICES_KERNEL
-class AttachOperation: public CHeapObj {
+class AttachOperation: public CHeapObj<mtInternal> {
public:
enum {
name_length_max = 16, // maximum length of name
--- a/hotspot/src/share/vm/services/diagnosticArgument.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/diagnosticArgument.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -140,7 +140,7 @@
if (str == NULL) {
_value = NULL;
} else {
- _value = NEW_C_HEAP_ARRAY(char, len+1);
+ _value = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
strncpy(_value, str, len);
_value[len] = 0;
}
@@ -159,7 +159,7 @@
template <> void DCmdArgument<char*>::destroy_value() {
if (_value != NULL) {
- FREE_C_HEAP_ARRAY(char, _value);
+ FREE_C_HEAP_ARRAY(char, _value, mtInternal);
set_value(NULL);
}
}
--- a/hotspot/src/share/vm/services/diagnosticArgument.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/diagnosticArgument.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -31,17 +31,17 @@
#include "runtime/thread.hpp"
#include "utilities/exceptions.hpp"
-class StringArrayArgument : public CHeapObj {
+class StringArrayArgument : public CHeapObj<mtInternal> {
private:
GrowableArray<char*>* _array;
public:
StringArrayArgument() {
- _array = new(ResourceObj::C_HEAP)GrowableArray<char *>(32, true);
+ _array = new(ResourceObj::C_HEAP, mtInternal)GrowableArray<char *>(32, true);
assert(_array != NULL, "Sanity check");
}
void add(const char* str, size_t len) {
if (str != NULL) {
- char* ptr = NEW_C_HEAP_ARRAY(char, len+1);
+ char* ptr = NEW_C_HEAP_ARRAY(char, len+1, mtInternal);
strncpy(ptr, str, len);
ptr[len] = 0;
_array->append(ptr);
@@ -53,7 +53,7 @@
~StringArrayArgument() {
for (int i=0; i<_array->length(); i++) {
if(_array->at(i) != NULL) { // Safety check
- FREE_C_HEAP_ARRAY(char, _array->at(i));
+ FREE_C_HEAP_ARRAY(char, _array->at(i), mtInternal);
}
}
delete _array;
--- a/hotspot/src/share/vm/services/diagnosticCommand.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -48,7 +48,7 @@
"With no argument this will show a list of available commands. "
"'help all' will show help for all commands.";
}
- static const char* impact() { return "Low: "; }
+ static const char* impact() { return "Low"; }
static int num_arguments();
virtual void execute(TRAPS);
};
@@ -60,7 +60,7 @@
static const char* description() {
return "Print JVM version information.";
}
- static const char* impact() { return "Low: "; }
+ static const char* impact() { return "Low"; }
static int num_arguments() { return 0; }
virtual void execute(TRAPS);
};
@@ -72,7 +72,7 @@
static const char* description() {
return "Print the command line used to start this VM instance.";
}
- static const char* impact() { return "Low: "; }
+ static const char* impact() { return "Low"; }
static int num_arguments() { return 0; }
virtual void execute(TRAPS) {
Arguments::print_on(_output);
@@ -88,7 +88,7 @@
return "Print system properties.";
}
static const char* impact() {
- return "Low: ";
+ return "Low";
}
static int num_arguments() { return 0; }
virtual void execute(TRAPS);
@@ -105,7 +105,7 @@
return "Print VM flag options and their current values.";
}
static const char* impact() {
- return "Low: ";
+ return "Low";
}
static int num_arguments();
virtual void execute(TRAPS);
@@ -121,7 +121,7 @@
return "Print VM uptime.";
}
static const char* impact() {
- return "Low: ";
+ return "Low";
}
static int num_arguments();
virtual void execute(TRAPS);
--- a/hotspot/src/share/vm/services/diagnosticFramework.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/diagnosticFramework.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -75,11 +75,13 @@
}
// extracting first item, argument or option name
_key_addr = &_buffer[_cursor];
+ bool arg_had_quotes = false;
while (_cursor <= _len - 1 && _buffer[_cursor] != '=' && _buffer[_cursor] != _delim) {
// argument can be surrounded by single or double quotes
if (_buffer[_cursor] == '\"' || _buffer[_cursor] == '\'') {
_key_addr++;
char quote = _buffer[_cursor];
+ arg_had_quotes = true;
while (_cursor < _len - 1) {
_cursor++;
if (_buffer[_cursor] == quote && _buffer[_cursor - 1] != '\\') {
@@ -95,16 +97,22 @@
_cursor++;
}
_key_len = &_buffer[_cursor] - _key_addr;
+ if (arg_had_quotes) {
+ // if the argument was quoted, we need to step past the last quote here
+ _cursor++;
+ }
// check if the argument has the <key>=<value> format
if (_cursor <= _len -1 && _buffer[_cursor] == '=') {
_cursor++;
_value_addr = &_buffer[_cursor];
+ bool value_had_quotes = false;
// extract the value
while (_cursor <= _len - 1 && _buffer[_cursor] != _delim) {
// value can be surrounded by simple or double quotes
if (_buffer[_cursor] == '\"' || _buffer[_cursor] == '\'') {
_value_addr++;
char quote = _buffer[_cursor];
+ value_had_quotes = true;
while (_cursor < _len - 1) {
_cursor++;
if (_buffer[_cursor] == quote && _buffer[_cursor - 1] != '\\') {
@@ -120,6 +128,10 @@
_cursor++;
}
_value_len = &_buffer[_cursor] - _value_addr;
+ if (value_had_quotes) {
+ // if the value was quoted, we need to step past the last quote here
+ _cursor++;
+ }
} else {
_value_addr = NULL;
_value_len = 0;
@@ -185,8 +197,17 @@
arg->read_value(iter.key_addr(), iter.key_length(), CHECK);
next_argument = next_argument->next();
} else {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Unknown argument in diagnostic command");
+ const size_t buflen = 120;
+ const size_t argbuflen = 30;
+ char buf[buflen];
+ char argbuf[argbuflen];
+ size_t len = MIN2<size_t>(iter.key_length(), argbuflen - 1);
+
+ strncpy(argbuf, iter.key_addr(), len);
+ argbuf[len] = '\0';
+ jio_snprintf(buf, buflen - 1, "Unknown argument '%s' in diagnostic command.", argbuf);
+
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
}
}
cont = iter.next(CHECK);
@@ -207,19 +228,21 @@
}
void DCmdParser::check(TRAPS) {
+ const size_t buflen = 256;
+ char buf[buflen];
GenDCmdArgument* arg = _arguments_list;
while (arg != NULL) {
if (arg->is_mandatory() && !arg->has_value()) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Missing argument for diagnostic command");
+ jio_snprintf(buf, buflen - 1, "The argument '%s' is mandatory.", arg->name());
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
}
arg = arg->next();
}
arg = _options;
while (arg != NULL) {
if (arg->is_mandatory() && !arg->has_value()) {
- THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Missing option for diagnostic command");
+ jio_snprintf(buf, buflen - 1, "The option '%s' is mandatory.", arg->name());
+ THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), buf);
}
arg = arg->next();
}
--- a/hotspot/src/share/vm/services/diagnosticFramework.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/diagnosticFramework.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -238,6 +238,16 @@
static const char* name() { return "No Name";}
static const char* description() { return "No Help";}
static const char* disabled_message() { return "Diagnostic command currently disabled"; }
+ // The impact() method returns a description of the intrusiveness of the diagnostic
+ // command on the Java Virtual Machine behavior. The rational for this method is that some
+ // diagnostic commands can seriously disrupt the behavior of the Java Virtual Machine
+ // (for instance a Thread Dump for an application with several tens of thousands of threads,
+ // or a Head Dump with a 40GB+ heap size) and other diagnostic commands have no serious
+ // impact on the JVM (for instance, getting the command line arguments or the JVM version).
+ // The recommended format for the description is <impact level>: [longer description],
+ // where the impact level is selected among this list: {Low, Medium, High}. The optional
+ // longer description can provide more specific details like the fact that Thread Dump
+ // impact depends on the heap size.
static const char* impact() { return "Low: No impact"; }
static int num_arguments() { return 0; }
outputStream* output() { return _output; }
@@ -250,7 +260,7 @@
bool has_arg = iter.next(CHECK);
if (has_arg) {
THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(),
- "Unknown argument in diagnostic command");
+ "The argument list of this diagnostic command should be empty.");
}
}
virtual void execute(TRAPS) { }
@@ -310,7 +320,7 @@
// manages the status of the diagnostic command (hidden, enabled). A DCmdFactory
// has to be registered to make the diagnostic command available (see
// management.cpp)
-class DCmdFactory: public CHeapObj {
+class DCmdFactory: public CHeapObj<mtInternal> {
private:
static Mutex* _dcmdFactory_lock;
// Pointer to the next factory in the singly-linked list of registered
@@ -368,7 +378,7 @@
DCmdFactory(DCmdClass::num_arguments(), enabled, hidden) { }
// Returns a C-heap allocated instance
virtual DCmd* create_Cheap_instance(outputStream* output) {
- return new (ResourceObj::C_HEAP) DCmdClass(output, true);
+ return new (ResourceObj::C_HEAP, mtInternal) DCmdClass(output, true);
}
// Returns a resourceArea allocated instance
virtual DCmd* create_resource_instance(outputStream* output) {
--- a/hotspot/src/share/vm/services/gcNotifier.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/gcNotifier.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -45,7 +45,7 @@
// GC may occur between now and the creation of the notification
int num_pools = MemoryService::num_memory_pools();
// stat is deallocated inside GCNotificationRequest
- GCStatInfo* stat = new(ResourceObj::C_HEAP) GCStatInfo(num_pools);
+ GCStatInfo* stat = new(ResourceObj::C_HEAP, mtGC) GCStatInfo(num_pools);
mgr->get_last_gc_stat(stat);
GCNotificationRequest *request = new GCNotificationRequest(os::javaTimeMillis(),mgr,action,cause,stat);
addRequest(request);
--- a/hotspot/src/share/vm/services/gcNotifier.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/gcNotifier.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -30,7 +30,7 @@
#include "services/memoryService.hpp"
#include "services/memoryManager.hpp"
-class GCNotificationRequest : public CHeapObj {
+class GCNotificationRequest : public CHeapObj<mtInternal> {
friend class GCNotifier;
GCNotificationRequest *next;
jlong timestamp;
--- a/hotspot/src/share/vm/services/heapDumper.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/heapDumper.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -436,7 +436,7 @@
// sufficient memory then reduce size until we can allocate something.
_size = io_buffer_size;
do {
- _buffer = (char*)os::malloc(_size);
+ _buffer = (char*)os::malloc(_size, mtInternal);
if (_buffer == NULL) {
_size = _size >> 1;
}
@@ -1405,7 +1405,7 @@
_gc_before_heap_dump = gc_before_heap_dump;
_is_segmented_dump = false;
_dump_start = (jlong)-1;
- _klass_map = new (ResourceObj::C_HEAP) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true);
+ _klass_map = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<Klass*>(INITIAL_CLASS_COUNT, true);
_stack_traces = NULL;
_num_threads = 0;
if (oome) {
@@ -1426,7 +1426,7 @@
for (int i=0; i < _num_threads; i++) {
delete _stack_traces[i];
}
- FREE_C_HEAP_ARRAY(ThreadStackTrace*, _stack_traces);
+ FREE_C_HEAP_ARRAY(ThreadStackTrace*, _stack_traces, mtInternal);
}
delete _klass_map;
}
@@ -1806,7 +1806,7 @@
writer()->write_u4(0); // thread number
writer()->write_u4(0); // frame count
- _stack_traces = NEW_C_HEAP_ARRAY(ThreadStackTrace*, Threads::number_of_threads());
+ _stack_traces = NEW_C_HEAP_ARRAY(ThreadStackTrace*, Threads::number_of_threads(), mtInternal);
int frame_serial_num = 0;
for (JavaThread* thread = Threads::first(); thread != NULL ; thread = thread->next()) {
oop threadObj = thread->threadObj();
@@ -2005,7 +2005,7 @@
dump_file_name, os::current_process_id(), dump_file_ext);
}
const size_t len = strlen(base_path) + 1;
- my_path = (char*)os::malloc(len);
+ my_path = (char*)os::malloc(len, mtInternal);
if (my_path == NULL) {
warning("Cannot create heap dump file. Out of system memory.");
return;
@@ -2014,7 +2014,7 @@
} else {
// Append a sequence number id for dumps following the first
const size_t len = strlen(base_path) + max_digit_chars + 2; // for '.' and \0
- my_path = (char*)os::malloc(len);
+ my_path = (char*)os::malloc(len, mtInternal);
if (my_path == NULL) {
warning("Cannot create heap dump file. Out of system memory.");
return;
--- a/hotspot/src/share/vm/services/lowMemoryDetector.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/lowMemoryDetector.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -63,7 +63,7 @@
class OopClosure;
class MemoryPool;
-class ThresholdSupport : public CHeapObj {
+class ThresholdSupport : public CHeapObj<mtInternal> {
private:
bool _support_high_threshold;
bool _support_low_threshold;
@@ -112,7 +112,7 @@
}
};
-class SensorInfo : public CHeapObj {
+class SensorInfo : public CHeapObj<mtInternal> {
private:
instanceOop _sensor_obj;
bool _sensor_on;
--- a/hotspot/src/share/vm/services/management.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/management.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -47,6 +47,7 @@
#include "services/jmm.h"
#include "services/lowMemoryDetector.hpp"
#include "services/gcNotifier.hpp"
+#include "services/nmtDCmd.hpp"
#include "services/management.hpp"
#include "services/memoryManager.hpp"
#include "services/memoryPool.hpp"
@@ -121,6 +122,7 @@
// Registration of the diagnostic commands
DCmdRegistrant::register_dcmds();
DCmdRegistrant::register_dcmds_ext();
+ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl<NMTDCmd>(true, false));
}
void Management::initialize(TRAPS) {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memBaseline.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,387 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "memory/allocation.hpp"
+#include "services/memBaseline.hpp"
+#include "services/memTracker.hpp"
+
+MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = {
+ {mtJavaHeap, "Java Heap"},
+ {mtClass, "Class"},
+ {mtThreadStack,"Thread Stack"},
+ {mtThread, "Thread"},
+ {mtCode, "Code"},
+ {mtGC, "GC"},
+ {mtCompiler, "Compiler"},
+ {mtInternal, "Internal"},
+ {mtOther, "Other"},
+ {mtSymbol, "Symbol"},
+ {mtNMT, "Memory Tracking"},
+ {mtChunk, "Pooled Free Chunks"},
+ {mtNone, "Unknown"} // It can happen when type tagging records are lagging
+ // behind
+};
+
+MemBaseline::MemBaseline() {
+ _baselined = false;
+
+ for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
+ _malloc_data[index].set_type(MemType2NameMap[index]._flag);
+ _vm_data[index].set_type(MemType2NameMap[index]._flag);
+ _arena_data[index].set_type(MemType2NameMap[index]._flag);
+ }
+
+ _malloc_cs = NULL;
+ _vm_cs = NULL;
+
+ _number_of_classes = 0;
+ _number_of_threads = 0;
+}
+
+
+void MemBaseline::clear() {
+ if (_malloc_cs != NULL) {
+ delete _malloc_cs;
+ _malloc_cs = NULL;
+ }
+
+ if (_vm_cs != NULL) {
+ delete _vm_cs;
+ _vm_cs = NULL;
+ }
+
+ reset();
+}
+
+
+void MemBaseline::reset() {
+ _baselined = false;
+ _total_vm_reserved = 0;
+ _total_vm_committed = 0;
+ _total_malloced = 0;
+ _number_of_classes = 0;
+
+ if (_malloc_cs != NULL) _malloc_cs->clear();
+ if (_vm_cs != NULL) _vm_cs->clear();
+
+ for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
+ _malloc_data[index].clear();
+ _vm_data[index].clear();
+ _arena_data[index].clear();
+ }
+}
+
+MemBaseline::~MemBaseline() {
+ if (_malloc_cs != NULL) {
+ delete _malloc_cs;
+ }
+
+ if (_vm_cs != NULL) {
+ delete _vm_cs;
+ }
+}
+
+// baseline malloc'd memory records, generate overall summary and summaries by
+// memory types
+bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) {
+ MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records);
+ MemPointerRecord* mptr = (MemPointerRecord*)mItr.current();
+ size_t used_arena_size = 0;
+ int index;
+ while (mptr != NULL) {
+ index = flag2index(FLAGS_TO_MEMORY_TYPE(mptr->flags()));
+ size_t size = mptr->size();
+ _total_malloced += size;
+ _malloc_data[index].inc(size);
+ if (MemPointerRecord::is_arena_record(mptr->flags())) {
+ // see if arena size record present
+ MemPointerRecord* next_p = (MemPointerRecordEx*)mItr.peek_next();
+ if (MemPointerRecord::is_arena_size_record(next_p->flags())) {
+ assert(next_p->is_size_record_of_arena(mptr), "arena records do not match");
+ size = next_p->size();
+ _arena_data[index].inc(size);
+ used_arena_size += size;
+ mItr.next();
+ }
+ }
+ mptr = (MemPointerRecordEx*)mItr.next();
+ }
+
+ // substract used arena size to get size of arena chunk in free list
+ index = flag2index(mtChunk);
+ _malloc_data[index].reduce(used_arena_size);
+ // we really don't know how many chunks in free list, so just set to
+ // 0
+ _malloc_data[index].overwrite_counter(0);
+
+ return true;
+}
+
+// baseline mmap'd memory records, generate overall summary and summaries by
+// memory types
+bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) {
+ MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records);
+ VMMemRegion* vptr = (VMMemRegion*)vItr.current();
+ int index;
+ while (vptr != NULL) {
+ index = flag2index(FLAGS_TO_MEMORY_TYPE(vptr->flags()));
+
+ // we use the number of thread stack to count threads
+ if (IS_MEMORY_TYPE(vptr->flags(), mtThreadStack)) {
+ _number_of_threads ++;
+ }
+ _total_vm_reserved += vptr->reserved_size();
+ _total_vm_committed += vptr->committed_size();
+ _vm_data[index].inc(vptr->reserved_size(), vptr->committed_size());
+ vptr = (VMMemRegion*)vItr.next();
+ }
+ return true;
+}
+
+// baseline malloc'd memory by callsites, but only the callsites with memory allocation
+// over 1KB are stored.
+bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) {
+ assert(MemTracker::track_callsite(), "detail tracking is off");
+
+ MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records);
+ MemPointerRecordEx* mptr = (MemPointerRecordEx*)mItr.current();
+ MallocCallsitePointer mp;
+
+ if (_malloc_cs == NULL) {
+ _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64);
+ // out of native memory
+ if (_malloc_cs == NULL) {
+ return false;
+ }
+ } else {
+ _malloc_cs->clear();
+ }
+
+ // baseline memory that is totaled over 1 KB
+ while (mptr != NULL) {
+ if (!MemPointerRecord::is_arena_size_record(mptr->flags())) {
+ // skip thread stacks
+ if (!IS_MEMORY_TYPE(mptr->flags(), mtThreadStack)) {
+ if (mp.addr() != mptr->pc()) {
+ if ((mp.amount()/K) > 0) {
+ if (!_malloc_cs->append(&mp)) {
+ return false;
+ }
+ }
+ mp = MallocCallsitePointer(mptr->pc());
+ }
+ mp.inc(mptr->size());
+ }
+ }
+ mptr = (MemPointerRecordEx*)mItr.next();
+ }
+
+ if (mp.addr() != 0 && (mp.amount()/K) > 0) {
+ if (!_malloc_cs->append(&mp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// baseline mmap'd memory by callsites
+bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) {
+ assert(MemTracker::track_callsite(), "detail tracking is off");
+
+ VMCallsitePointer vp;
+ MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records);
+ VMMemRegionEx* vptr = (VMMemRegionEx*)vItr.current();
+
+ if (_vm_cs == NULL) {
+ _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64);
+ if (_vm_cs == NULL) {
+ return false;
+ }
+ } else {
+ _vm_cs->clear();
+ }
+
+ while (vptr != NULL) {
+ if (vp.addr() != vptr->pc()) {
+ if (!_vm_cs->append(&vp)) {
+ return false;
+ }
+ vp = VMCallsitePointer(vptr->pc());
+ }
+ vp.inc(vptr->size(), vptr->committed_size());
+ vptr = (VMMemRegionEx*)vItr.next();
+ }
+ if (vp.addr() != 0) {
+ if (!_vm_cs->append(&vp)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// baseline a snapshot. If summary_only = false, memory usages aggregated by
+// callsites are also baselined.
+bool MemBaseline::baseline(MemSnapshot& snapshot, bool summary_only) {
+ MutexLockerEx snapshot_locker(snapshot._lock, true);
+ reset();
+ _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) &&
+ baseline_vm_summary(snapshot._vm_ptrs);
+ _number_of_classes = SystemDictionary::number_of_classes();
+
+ if (!summary_only && MemTracker::track_callsite() && _baselined) {
+ ((MemPointerArray*)snapshot._alloc_ptrs)->sort((FN_SORT)malloc_sort_by_pc);
+ ((MemPointerArray*)snapshot._vm_ptrs)->sort((FN_SORT)vm_sort_by_pc);
+ _baselined = baseline_malloc_details(snapshot._alloc_ptrs) &&
+ baseline_vm_details(snapshot._vm_ptrs);
+ ((MemPointerArray*)snapshot._alloc_ptrs)->sort((FN_SORT)malloc_sort_by_addr);
+ ((MemPointerArray*)snapshot._vm_ptrs)->sort((FN_SORT)vm_sort_by_addr);
+ }
+ return _baselined;
+}
+
+
+int MemBaseline::flag2index(MEMFLAGS flag) const {
+ for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
+ if (MemType2NameMap[index]._flag == flag) {
+ return index;
+ }
+ }
+ assert(false, "no type");
+ return -1;
+}
+
+const char* MemBaseline::type2name(MEMFLAGS type) {
+ for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
+ if (MemType2NameMap[index]._flag == type) {
+ return MemType2NameMap[index]._name;
+ }
+ }
+ assert(false, "no type");
+ return NULL;
+}
+
+
+MemBaseline& MemBaseline::operator=(const MemBaseline& other) {
+ _total_malloced = other._total_malloced;
+ _total_vm_reserved = other._total_vm_reserved;
+ _total_vm_committed = other._total_vm_committed;
+
+ _baselined = other._baselined;
+ _number_of_classes = other._number_of_classes;
+
+ for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
+ _malloc_data[index] = other._malloc_data[index];
+ _vm_data[index] = other._vm_data[index];
+ _arena_data[index] = other._arena_data[index];
+ }
+
+ if (MemTracker::track_callsite()) {
+ assert(_malloc_cs != NULL && _vm_cs != NULL, "out of memory");
+ assert(other._malloc_cs != NULL && other._vm_cs != NULL,
+ "not properly baselined");
+ _malloc_cs->clear();
+ _vm_cs->clear();
+ int index;
+ for (index = 0; index < other._malloc_cs->length(); index ++) {
+ _malloc_cs->append(other._malloc_cs->at(index));
+ }
+
+ for (index = 0; index < other._vm_cs->length(); index ++) {
+ _vm_cs->append(other._vm_cs->at(index));
+ }
+ }
+ return *this;
+}
+
+/* compare functions for sorting */
+
+// sort snapshot malloc'd records in callsite pc order
+int MemBaseline::malloc_sort_by_pc(const void* p1, const void* p2) {
+ assert(MemTracker::track_callsite(),"Just check");
+ const MemPointerRecordEx* mp1 = (const MemPointerRecordEx*)p1;
+ const MemPointerRecordEx* mp2 = (const MemPointerRecordEx*)p2;
+ return UNSIGNED_COMPARE(mp1->pc(), mp2->pc());
+}
+
+// sort baselined malloc'd records in size order
+int MemBaseline::bl_malloc_sort_by_size(const void* p1, const void* p2) {
+ assert(MemTracker::is_on(), "Just check");
+ const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1;
+ const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2;
+ return UNSIGNED_COMPARE(mp2->amount(), mp1->amount());
+}
+
+// sort baselined malloc'd records in callsite pc order
+int MemBaseline::bl_malloc_sort_by_pc(const void* p1, const void* p2) {
+ assert(MemTracker::is_on(), "Just check");
+ const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1;
+ const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2;
+ return UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
+}
+
+// sort snapshot mmap'd records in callsite pc order
+int MemBaseline::vm_sort_by_pc(const void* p1, const void* p2) {
+ assert(MemTracker::track_callsite(),"Just check");
+ const VMMemRegionEx* mp1 = (const VMMemRegionEx*)p1;
+ const VMMemRegionEx* mp2 = (const VMMemRegionEx*)p2;
+ return UNSIGNED_COMPARE(mp1->pc(), mp2->pc());
+}
+
+// sort baselined mmap'd records in size (reserved size) order
+int MemBaseline::bl_vm_sort_by_size(const void* p1, const void* p2) {
+ assert(MemTracker::is_on(), "Just check");
+ const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1;
+ const VMCallsitePointer* mp2 = (const VMCallsitePointer*)p2;
+ return UNSIGNED_COMPARE(mp2->reserved_amount(), mp1->reserved_amount());
+}
+
+// sort baselined mmap'd records in callsite pc order
+int MemBaseline::bl_vm_sort_by_pc(const void* p1, const void* p2) {
+ assert(MemTracker::is_on(), "Just check");
+ const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1;
+ const VMCallsitePointer* mp2 = (const VMCallsitePointer*)p2;
+ return UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
+}
+
+
+// sort snapshot malloc'd records in memory block address order
+int MemBaseline::malloc_sort_by_addr(const void* p1, const void* p2) {
+ assert(MemTracker::is_on(), "Just check");
+ 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");
+ return delta;
+}
+
+// sort snapshot mmap'd records in memory block address order
+int MemBaseline::vm_sort_by_addr(const void* p1, const void* p2) {
+ assert(MemTracker::is_on(), "Just check");
+ const VMMemRegion* mp1 = (const VMMemRegion*)p1;
+ const VMMemRegion* mp2 = (const VMMemRegion*)p2;
+ int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
+ assert(delta != 0, "dup pointer");
+ return delta;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memBaseline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,447 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_MEM_BASELINE_HPP
+#define SHARE_VM_SERVICES_MEM_BASELINE_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/mutex.hpp"
+#include "services/memPtr.hpp"
+#include "services/memSnapshot.hpp"
+
+// compare unsigned number
+#define UNSIGNED_COMPARE(a, b) ((a > b) ? 1 : ((a == b) ? 0 : -1))
+
+/*
+ * MallocCallsitePointer and VMCallsitePointer are used
+ * to baseline memory blocks with their callsite information.
+ * They are only available when detail tracking is turned
+ * on.
+ */
+
+/* baselined malloc record aggregated by callsite */
+class MallocCallsitePointer : public MemPointer {
+ private:
+ size_t _count; // number of malloc invocation from this callsite
+ size_t _amount; // total amount of memory malloc-ed from this callsite
+
+ public:
+ MallocCallsitePointer() {
+ _count = 0;
+ _amount = 0;
+ }
+
+ MallocCallsitePointer(address pc) : MemPointer(pc) {
+ _count = 0;
+ _amount = 0;
+ }
+
+ MallocCallsitePointer& operator=(const MallocCallsitePointer& p) {
+ MemPointer::operator=(p);
+ _count = p.count();
+ _amount = p.amount();
+ return *this;
+ }
+
+ inline void inc(size_t size) {
+ _count ++;
+ _amount += size;
+ };
+
+ inline size_t count() const {
+ return _count;
+ }
+
+ inline size_t amount() const {
+ return _amount;
+ }
+};
+
+// baselined virtual memory record aggregated by callsite
+class VMCallsitePointer : public MemPointer {
+ private:
+ size_t _count; // number of invocation from this callsite
+ size_t _reserved_amount; // total reserved amount
+ size_t _committed_amount; // total committed amount
+
+ public:
+ VMCallsitePointer() {
+ _count = 0;
+ _reserved_amount = 0;
+ _committed_amount = 0;
+ }
+
+ VMCallsitePointer(address pc) : MemPointer(pc) {
+ _count = 0;
+ _reserved_amount = 0;
+ _committed_amount = 0;
+ }
+
+ VMCallsitePointer& operator=(const VMCallsitePointer& p) {
+ MemPointer::operator=(p);
+ _count = p.count();
+ _reserved_amount = p.reserved_amount();
+ _committed_amount = p.committed_amount();
+ return *this;
+ }
+
+ inline void inc(size_t reserved, size_t committed) {
+ _count ++;
+ _reserved_amount += reserved;
+ _committed_amount += committed;
+ }
+
+ inline size_t count() const {
+ return _count;
+ }
+
+ inline size_t reserved_amount() const {
+ return _reserved_amount;
+ }
+
+ inline size_t committed_amount() const {
+ return _committed_amount;
+ }
+};
+
+// maps a memory type flag to readable name
+typedef struct _memType2Name {
+ MEMFLAGS _flag;
+ const char* _name;
+} MemType2Name;
+
+
+// This class aggregates malloc'd records by memory type
+class MallocMem : public _ValueObj {
+ private:
+ MEMFLAGS _type;
+
+ size_t _count;
+ size_t _amount;
+
+ public:
+ MallocMem() {
+ _type = mtNone;
+ _count = 0;
+ _amount = 0;
+ }
+
+ MallocMem(MEMFLAGS flags) {
+ assert(HAS_VALID_MEMORY_TYPE(flags), "no type");
+ _type = FLAGS_TO_MEMORY_TYPE(flags);
+ _count = 0;
+ _amount = 0;
+ }
+
+ inline void set_type(MEMFLAGS flag) {
+ _type = flag;
+ }
+
+ inline void clear() {
+ _count = 0;
+ _amount = 0;
+ _type = mtNone;
+ }
+
+ MallocMem& operator=(const MallocMem& m) {
+ assert(_type == m.type(), "different type");
+ _count = m.count();
+ _amount = m.amount();
+ return *this;
+ }
+
+ inline void inc(size_t amt) {
+ _amount += amt;
+ _count ++;
+ }
+
+ inline void reduce(size_t amt) {
+ assert(_amount >= amt, "Just check");
+ _amount -= amt;
+ }
+
+ inline void overwrite_counter(size_t count) {
+ _count = count;
+ }
+
+ inline MEMFLAGS type() const {
+ return _type;
+ }
+
+ inline bool is_type(MEMFLAGS flags) const {
+ return FLAGS_TO_MEMORY_TYPE(flags) == _type;
+ }
+
+ inline size_t count() const {
+ return _count;
+ }
+
+ inline size_t amount() const {
+ return _amount;
+ }
+};
+
+// This class records live arena's memory usage
+class ArenaMem : public MallocMem {
+ public:
+ ArenaMem(MEMFLAGS typeflag): MallocMem(typeflag) {
+ }
+ ArenaMem() { }
+};
+
+// This class aggregates virtual memory by its memory type
+class VMMem : public _ValueObj {
+ private:
+ MEMFLAGS _type;
+
+ size_t _count;
+ size_t _reserved_amount;
+ size_t _committed_amount;
+
+ public:
+ VMMem() {
+ _type = mtNone;
+ _count = 0;
+ _reserved_amount = 0;
+ _committed_amount = 0;
+ }
+
+ VMMem(MEMFLAGS flags) {
+ assert(HAS_VALID_MEMORY_TYPE(flags), "no type");
+ _type = FLAGS_TO_MEMORY_TYPE(flags);
+ _count = 0;
+ _reserved_amount = 0;
+ _committed_amount = 0;
+ }
+
+ inline void clear() {
+ _type = mtNone;
+ _count = 0;
+ _reserved_amount = 0;
+ _committed_amount = 0;
+ }
+
+ inline void set_type(MEMFLAGS flags) {
+ _type = FLAGS_TO_MEMORY_TYPE(flags);
+ }
+
+ VMMem& operator=(const VMMem& m) {
+ assert(_type == m.type(), "different type");
+
+ _count = m.count();
+ _reserved_amount = m.reserved_amount();
+ _committed_amount = m.committed_amount();
+ return *this;
+ }
+
+
+ inline MEMFLAGS type() const {
+ return _type;
+ }
+
+ inline bool is_type(MEMFLAGS flags) const {
+ return FLAGS_TO_MEMORY_TYPE(flags) == _type;
+ }
+
+ inline void inc(size_t reserved_amt, size_t committed_amt) {
+ _reserved_amount += reserved_amt;
+ _committed_amount += committed_amt;
+ _count ++;
+ }
+
+ inline size_t count() const {
+ return _count;
+ }
+
+ inline size_t reserved_amount() const {
+ return _reserved_amount;
+ }
+
+ inline size_t committed_amount() const {
+ return _committed_amount;
+ }
+};
+
+
+
+#define NUMBER_OF_MEMORY_TYPE (mt_number_of_types + 1)
+
+class BaselineReporter;
+class BaselineComparisonReporter;
+
+/*
+ * This class baselines current memory snapshot.
+ * A memory baseline summarizes memory usage by memory type,
+ * aggregates memory usage by callsites when detail tracking
+ * is on.
+ */
+class MemBaseline : public _ValueObj {
+ friend class BaselineReporter;
+ friend class BaselineComparisonReporter;
+
+ private:
+ // overall summaries
+ size_t _total_malloced;
+ size_t _total_vm_reserved;
+ size_t _total_vm_committed;
+ size_t _number_of_classes;
+ size_t _number_of_threads;
+
+ // if it has properly baselined
+ bool _baselined;
+
+ // we categorize memory into three categories within the memory type
+ MallocMem _malloc_data[NUMBER_OF_MEMORY_TYPE];
+ VMMem _vm_data[NUMBER_OF_MEMORY_TYPE];
+ ArenaMem _arena_data[NUMBER_OF_MEMORY_TYPE];
+
+ // memory records that aggregate memory usage by callsites.
+ // only available when detail tracking is on.
+ MemPointerArray* _malloc_cs;
+ MemPointerArray* _vm_cs;
+
+ private:
+ static MemType2Name MemType2NameMap[NUMBER_OF_MEMORY_TYPE];
+
+ private:
+ // should not use copy constructor
+ MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); }
+
+ public:
+ // create a memory baseline
+ MemBaseline();
+
+ virtual ~MemBaseline();
+
+ inline bool baselined() const {
+ return _baselined;
+ }
+
+ MemBaseline& operator=(const MemBaseline& other);
+
+ // reset the baseline for reuse
+ void clear();
+
+ // baseline the snapshot
+ bool baseline(MemSnapshot& snapshot, bool summary_only = true);
+
+ bool baseline(const MemPointerArray* malloc_records,
+ const MemPointerArray* vm_records,
+ bool summary_only = true);
+
+ // total malloc'd memory of specified memory type
+ inline size_t malloc_amount(MEMFLAGS flag) const {
+ return _malloc_data[flag2index(flag)].amount();
+ }
+ // number of malloc'd memory blocks of specified memory type
+ inline size_t malloc_count(MEMFLAGS flag) const {
+ return _malloc_data[flag2index(flag)].count();
+ }
+ // total memory used by arenas of specified memory type
+ inline size_t arena_amount(MEMFLAGS flag) const {
+ return _arena_data[flag2index(flag)].amount();
+ }
+ // number of arenas of specified memory type
+ inline size_t arena_count(MEMFLAGS flag) const {
+ return _arena_data[flag2index(flag)].count();
+ }
+ // total reserved memory of specified memory type
+ inline size_t reserved_amount(MEMFLAGS flag) const {
+ return _vm_data[flag2index(flag)].reserved_amount();
+ }
+ // total committed memory of specified memory type
+ inline size_t committed_amount(MEMFLAGS flag) const {
+ return _vm_data[flag2index(flag)].committed_amount();
+ }
+ // total memory (malloc'd + mmap'd + arena) of specified
+ // memory type
+ inline size_t total_amount(MEMFLAGS flag) const {
+ int index = flag2index(flag);
+ return _malloc_data[index].amount() +
+ _vm_data[index].reserved_amount() +
+ _arena_data[index].amount();
+ }
+
+ /* overall summaries */
+
+ // total malloc'd memory in snapshot
+ inline size_t total_malloc_amount() const {
+ return _total_malloced;
+ }
+ // total mmap'd memory in snapshot
+ inline size_t total_reserved_amount() const {
+ return _total_vm_reserved;
+ }
+ // total committed memory in snapshot
+ inline size_t total_committed_amount() const {
+ return _total_vm_committed;
+ }
+ // number of loaded classes
+ inline size_t number_of_classes() const {
+ return _number_of_classes;
+ }
+ // number of running threads
+ inline size_t number_of_threads() const {
+ return _number_of_threads;
+ }
+ // lookup human readable name of a memory type
+ static const char* type2name(MEMFLAGS type);
+
+ private:
+ // convert memory flag to the index to mapping table
+ int flag2index(MEMFLAGS flag) const;
+
+ // reset baseline values
+ void reset();
+
+ // summarize the records in global snapshot
+ bool baseline_malloc_summary(const MemPointerArray* malloc_records);
+ bool baseline_vm_summary(const MemPointerArray* vm_records);
+ bool baseline_malloc_details(const MemPointerArray* malloc_records);
+ bool baseline_vm_details(const MemPointerArray* vm_records);
+
+ // print a line of malloc'd memory aggregated by callsite
+ void print_malloc_callsite(outputStream* st, address pc, size_t size,
+ size_t count, int diff_amt, int diff_count) const;
+ // print a line of mmap'd memory aggregated by callsite
+ void print_vm_callsite(outputStream* st, address pc, size_t rsz,
+ size_t csz, int diff_rsz, int diff_csz) const;
+
+ // sorting functions for raw records
+ static int malloc_sort_by_pc(const void* p1, const void* p2);
+ static int malloc_sort_by_addr(const void* p1, const void* p2);
+
+ static int vm_sort_by_pc(const void* p1, const void* p2);
+ static int vm_sort_by_addr(const void* p1, const void* p2);
+
+ private:
+ // sorting functions for baselined records
+ static int bl_malloc_sort_by_size(const void* p1, const void* p2);
+ static int bl_vm_sort_by_size(const void* p1, const void* p2);
+ static int bl_malloc_sort_by_pc(const void* p1, const void* p2);
+ static int bl_vm_sort_by_pc(const void* p1, const void* p2);
+};
+
+
+#endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memPtr.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "services/memPtr.hpp"
+#include "services/memTracker.hpp"
+
+volatile jint SequenceGenerator::_seq_number = 1;
+DEBUG_ONLY(jint SequenceGenerator::_max_seq_number = 1;)
+DEBUG_ONLY(volatile unsigned long SequenceGenerator::_generation = 0;)
+
+jint SequenceGenerator::next() {
+ jint seq = Atomic::add(1, &_seq_number);
+ if (seq < 0) {
+ MemTracker::shutdown(MemTracker::NMT_sequence_overflow);
+ }
+ assert(seq > 0, "counter overflow");
+ DEBUG_ONLY(_max_seq_number = (seq > _max_seq_number) ? seq : _max_seq_number;)
+ return seq;
+}
+
+
+
+bool VMMemRegion::contains(const VMMemRegion* mr) const {
+ assert(base() != 0, "no base address");
+ assert(size() != 0 || committed_size() != 0,
+ "no range");
+ address base_addr = base();
+ address end_addr = base_addr +
+ (is_reserve_record()? reserved_size(): committed_size());
+ if (mr->is_reserve_record()) {
+ if (mr->base() == base_addr && mr->size() == size()) {
+ // the same range
+ return true;
+ }
+ return false;
+ } else if (mr->is_commit_record() || mr->is_uncommit_record()) {
+ assert(mr->base() != 0 && mr->committed_size() > 0,
+ "bad record");
+ return (mr->base() >= base_addr &&
+ (mr->base() + mr->committed_size()) <= end_addr);
+ } else if (mr->is_type_tagging_record()) {
+ assert(mr->base() != 0, "no base");
+ return mr->base() == base_addr;
+ } else if (mr->is_release_record()) {
+ assert(mr->base() != 0 && mr->size() > 0,
+ "bad record");
+ return (mr->base() == base_addr && mr->size() == size());
+ } else {
+ assert(false, "what happened?");
+ return false;
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memPtr.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,509 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_MEM_PTR_HPP
+#define SHARE_VM_SERVICES_MEM_PTR_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "runtime/os.hpp"
+#include "runtime/safepoint.hpp"
+
+/*
+ * global sequence generator that generates sequence numbers to serialize
+ * memory records.
+ */
+class SequenceGenerator : AllStatic {
+ public:
+ static jint next();
+
+ // peek last sequence number
+ static jint peek() {
+ return _seq_number;
+ }
+
+ // reset sequence number
+ static void reset() {
+ assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
+ _seq_number = 1;
+ DEBUG_ONLY(_generation ++;)
+ };
+
+ DEBUG_ONLY(static unsigned long current_generation() { return (unsigned long)_generation; })
+ DEBUG_ONLY(static jint max_seq_num() { return _max_seq_number; })
+
+ private:
+ static volatile jint _seq_number;
+ DEBUG_ONLY(static jint _max_seq_number; )
+ DEBUG_ONLY(static volatile unsigned long _generation; )
+};
+
+/*
+ * followings are the classes that are used to hold memory activity records in different stages.
+ * MemPointer
+ * |--------MemPointerRecord
+ * |
+ * |----MemPointerRecordEx
+ * | |
+ * | |-------SeqMemPointerRecordEx
+ * |
+ * |----SeqMemPointerRecord
+ * |
+ * |----VMMemRegion
+ * |
+ * |-----VMMemRegionEx
+ *
+ *
+ * prefix 'Seq' - sequenced, the record contains a sequence number
+ * surfix 'Ex' - extension, the record contains a caller's pc
+ *
+ * per-thread recorder : SeqMemPointerRecord(Ex)
+ * snapshot staging : SeqMemPointerRecord(Ex)
+ * snapshot : MemPointerRecord(Ex) and VMMemRegion(Ex)
+ *
+ */
+
+/*
+ * class that wraps an address to a memory block,
+ * the memory pointer either points to a malloc'd
+ * memory block, or a mmap'd memory block
+ */
+class MemPointer : public _ValueObj {
+ public:
+ MemPointer(): _addr(0) { }
+ MemPointer(address addr): _addr(addr) { }
+
+ MemPointer(const MemPointer& copy_from) {
+ _addr = copy_from.addr();
+ }
+
+ inline address addr() const {
+ return _addr;
+ }
+
+ inline operator address() const {
+ return addr();
+ }
+
+ inline bool operator == (const MemPointer& other) const {
+ return addr() == other.addr();
+ }
+
+ inline MemPointer& operator = (const MemPointer& other) {
+ _addr = other.addr();
+ return *this;
+ }
+
+ protected:
+ inline void set_addr(address addr) { _addr = addr; }
+
+ protected:
+ // memory address
+ address _addr;
+};
+
+/* MemPointerRecord records an activityand associated
+ * attributes on a memory block.
+ */
+class MemPointerRecord : public MemPointer {
+ private:
+ MEMFLAGS _flags;
+ size_t _size;
+
+public:
+ /* extension of MemoryType enum
+ * see share/vm/memory/allocation.hpp for details.
+ *
+ * The tag values are associated to sorting orders, so be
+ * careful if changes are needed.
+ * The allocation records should be sorted ahead of tagging
+ * records, which in turn ahead of deallocation records
+ */
+ enum MemPointerTags {
+ tag_alloc = 0x0001, // malloc or reserve record
+ tag_commit = 0x0002, // commit record
+ tag_type = 0x0003, // tag virtual memory to a memory type
+ tag_uncommit = 0x0004, // uncommit record
+ tag_release = 0x0005, // free or release record
+ tag_size = 0x0006, // arena size
+ tag_masks = 0x0007, // all tag bits
+ vmBit = 0x0008
+ };
+
+ /* helper functions to interpret the tagging flags */
+
+ inline static bool is_allocation_record(MEMFLAGS flags) {
+ return (flags & tag_masks) == tag_alloc;
+ }
+
+ inline static bool is_deallocation_record(MEMFLAGS flags) {
+ return (flags & tag_masks) == tag_release;
+ }
+
+ inline static bool is_arena_record(MEMFLAGS flags) {
+ return (flags & (otArena | tag_size)) == otArena;
+ }
+
+ inline static bool is_arena_size_record(MEMFLAGS flags) {
+ return (flags & (otArena | tag_size)) == (otArena | tag_size);
+ }
+
+ inline static bool is_virtual_memory_record(MEMFLAGS flags) {
+ return (flags & vmBit) != 0;
+ }
+
+ inline static bool is_virtual_memory_reserve_record(MEMFLAGS flags) {
+ return (flags & 0x0F) == (tag_alloc | vmBit);
+ }
+
+ inline static bool is_virtual_memory_commit_record(MEMFLAGS flags) {
+ return (flags & 0x0F) == (tag_commit | vmBit);
+ }
+
+ inline static bool is_virtual_memory_uncommit_record(MEMFLAGS flags) {
+ return (flags & 0x0F) == (tag_uncommit | vmBit);
+ }
+
+ inline static bool is_virtual_memory_release_record(MEMFLAGS flags) {
+ return (flags & 0x0F) == (tag_release | vmBit);
+ }
+
+ inline static bool is_virtual_memory_type_record(MEMFLAGS flags) {
+ return (flags & 0x0F) == (tag_type | vmBit);
+ }
+
+ /* tagging flags */
+ inline static MEMFLAGS malloc_tag() { return tag_alloc; }
+ inline static MEMFLAGS free_tag() { return tag_release; }
+ inline static MEMFLAGS arena_size_tag() { return tag_size | otArena; }
+ inline static MEMFLAGS virtual_memory_tag() { return vmBit; }
+ inline static MEMFLAGS virtual_memory_reserve_tag() { return (tag_alloc | vmBit); }
+ inline static MEMFLAGS virtual_memory_commit_tag() { return (tag_commit | vmBit); }
+ inline static MEMFLAGS virtual_memory_uncommit_tag(){ return (tag_uncommit | vmBit); }
+ inline static MEMFLAGS virtual_memory_release_tag() { return (tag_release | vmBit); }
+ inline static MEMFLAGS virtual_memory_type_tag() { return (tag_type | vmBit); }
+
+ public:
+ MemPointerRecord(): _size(0), _flags(mtNone) { }
+
+ MemPointerRecord(address addr, MEMFLAGS memflags, size_t size = 0):
+ MemPointer(addr), _flags(memflags), _size(size) { }
+
+ MemPointerRecord(const MemPointerRecord& copy_from):
+ MemPointer(copy_from), _flags(copy_from.flags()),
+ _size(copy_from.size()) {
+ }
+
+ /* MemPointerRecord is not sequenced, it always return
+ * 0 to indicate non-sequenced
+ */
+ virtual jint seq() const { return 0; }
+
+ inline size_t size() const { return _size; }
+ inline void set_size(size_t size) { _size = size; }
+
+ inline MEMFLAGS flags() const { return _flags; }
+ inline void set_flags(MEMFLAGS flags) { _flags = flags; }
+
+ MemPointerRecord& operator= (const MemPointerRecord& ptr) {
+ MemPointer::operator=(ptr);
+ _flags = ptr.flags();
+#ifdef ASSERT
+ if (IS_ARENA_OBJ(_flags)) {
+ assert(!is_vm_pointer(), "wrong flags");
+ assert((_flags & ot_masks) == otArena, "wrong flags");
+ }
+#endif
+ _size = ptr.size();
+ return *this;
+ }
+
+ // if the pointer represents a malloc-ed memory address
+ inline bool is_malloced_pointer() const {
+ return !is_vm_pointer();
+ }
+
+ // if the pointer represents a virtual memory address
+ inline bool is_vm_pointer() const {
+ return is_virtual_memory_record(_flags);
+ }
+
+ // if this record records a 'malloc' or virtual memory
+ // 'reserve' call
+ inline bool is_allocation_record() const {
+ return is_allocation_record(_flags);
+ }
+
+ // if this record records a size information of an arena
+ inline bool is_arena_size_record() const {
+ return is_arena_size_record(_flags);
+ }
+
+ // if this pointer represents an address to an arena object
+ inline bool is_arena_record() const {
+ return is_arena_record(_flags);
+ }
+
+ // if this record represents a size information of specific arena
+ inline bool is_size_record_of_arena(const MemPointerRecord* arena_rc) {
+ assert(is_arena_size_record(), "not size record");
+ assert(arena_rc->is_arena_record(), "not arena record");
+ return (arena_rc->addr() + sizeof(void*)) == addr();
+ }
+
+ // if this record records a 'free' or virtual memory 'free' call
+ inline bool is_deallocation_record() const {
+ return is_deallocation_record(_flags);
+ }
+
+ // if this record records a virtual memory 'commit' call
+ inline bool is_commit_record() const {
+ return is_virtual_memory_commit_record(_flags);
+ }
+
+ // if this record records a virtual memory 'uncommit' call
+ inline bool is_uncommit_record() const {
+ return is_virtual_memory_uncommit_record(_flags);
+ }
+
+ // if this record is a tagging record of a virtual memory block
+ inline bool is_type_tagging_record() const {
+ return is_virtual_memory_type_record(_flags);
+ }
+};
+
+// MemPointerRecordEx also records callsite pc, from where
+// the memory block is allocated
+class MemPointerRecordEx : public MemPointerRecord {
+ private:
+ address _pc; // callsite pc
+
+ public:
+ MemPointerRecordEx(): _pc(0) { }
+
+ MemPointerRecordEx(address addr, MEMFLAGS memflags, size_t size = 0, address pc = 0):
+ MemPointerRecord(addr, memflags, size), _pc(pc) {}
+
+ MemPointerRecordEx(const MemPointerRecordEx& copy_from):
+ MemPointerRecord(copy_from), _pc(copy_from.pc()) {}
+
+ inline address pc() const { return _pc; }
+
+ void init(const MemPointerRecordEx* mpe) {
+ MemPointerRecord::operator=(*mpe);
+ _pc = mpe->pc();
+ }
+
+ void init(const MemPointerRecord* mp) {
+ MemPointerRecord::operator=(*mp);
+ _pc = 0;
+ }
+};
+
+// a virtual memory region
+class VMMemRegion : public MemPointerRecord {
+ private:
+ // committed size
+ size_t _committed_size;
+
+public:
+ VMMemRegion(): _committed_size(0) { }
+
+ void init(const MemPointerRecord* mp) {
+ assert(mp->is_vm_pointer(), "not virtual memory pointer");
+ _addr = mp->addr();
+ if (mp->is_commit_record() || mp->is_uncommit_record()) {
+ _committed_size = mp->size();
+ set_size(_committed_size);
+ } else {
+ set_size(mp->size());
+ _committed_size = 0;
+ }
+ set_flags(mp->flags());
+ }
+
+ VMMemRegion& operator=(const VMMemRegion& other) {
+ MemPointerRecord::operator=(other);
+ _committed_size = other.committed_size();
+ return *this;
+ }
+
+ inline bool is_reserve_record() const {
+ return is_virtual_memory_reserve_record(flags());
+ }
+
+ inline bool is_release_record() const {
+ return is_virtual_memory_release_record(flags());
+ }
+
+ // resize reserved VM range
+ inline void set_reserved_size(size_t new_size) {
+ assert(new_size >= committed_size(), "resize");
+ set_size(new_size);
+ }
+
+ inline void commit(size_t size) {
+ _committed_size += size;
+ }
+
+ inline void uncommit(size_t size) {
+ if (_committed_size >= size) {
+ _committed_size -= size;
+ } else {
+ _committed_size = 0;
+ }
+ }
+
+ /*
+ * if this virtual memory range covers whole range of
+ * the other VMMemRegion
+ */
+ bool contains(const VMMemRegion* mr) const;
+
+ /* base address of this virtual memory range */
+ inline address base() const {
+ return addr();
+ }
+
+ /* tag this virtual memory range to the specified memory type */
+ inline void tag(MEMFLAGS f) {
+ set_flags(flags() | (f & mt_masks));
+ }
+
+ // release part of memory range
+ inline void partial_release(address add, size_t sz) {
+ assert(add >= addr() && add < addr() + size(), "not valid address");
+ // for now, it can partially release from the both ends,
+ // but not in the middle
+ assert(add == addr() || (add + sz) == (addr() + size()),
+ "release in the middle");
+ if (add == addr()) {
+ set_addr(add + sz);
+ set_size(size() - sz);
+ } else {
+ set_size(size() - sz);
+ }
+ }
+
+ // the committed size of the virtual memory block
+ inline size_t committed_size() const {
+ return _committed_size;
+ }
+
+ // the reserved size of the virtual memory block
+ inline size_t reserved_size() const {
+ return size();
+ }
+};
+
+class VMMemRegionEx : public VMMemRegion {
+ private:
+ jint _seq; // sequence number
+
+ public:
+ VMMemRegionEx(): _pc(0) { }
+
+ void init(const MemPointerRecordEx* mpe) {
+ VMMemRegion::init(mpe);
+ _pc = mpe->pc();
+ }
+
+ void init(const MemPointerRecord* mpe) {
+ VMMemRegion::init(mpe);
+ _pc = 0;
+ }
+
+ VMMemRegionEx& operator=(const VMMemRegionEx& other) {
+ VMMemRegion::operator=(other);
+ _pc = other.pc();
+ return *this;
+ }
+
+ inline address pc() const { return _pc; }
+ private:
+ address _pc;
+};
+
+/*
+ * Sequenced memory record
+ */
+class SeqMemPointerRecord : public MemPointerRecord {
+ private:
+ jint _seq; // sequence number
+
+ public:
+ SeqMemPointerRecord(): _seq(0){ }
+
+ SeqMemPointerRecord(address addr, MEMFLAGS flags, size_t size)
+ : MemPointerRecord(addr, flags, size) {
+ _seq = SequenceGenerator::next();
+ }
+
+ SeqMemPointerRecord(const SeqMemPointerRecord& copy_from)
+ : MemPointerRecord(copy_from) {
+ _seq = copy_from.seq();
+ }
+
+ SeqMemPointerRecord& operator= (const SeqMemPointerRecord& ptr) {
+ MemPointerRecord::operator=(ptr);
+ _seq = ptr.seq();
+ return *this;
+ }
+
+ inline jint seq() const {
+ return _seq;
+ }
+};
+
+
+
+class SeqMemPointerRecordEx : public MemPointerRecordEx {
+ private:
+ jint _seq; // sequence number
+
+ public:
+ SeqMemPointerRecordEx(): _seq(0) { }
+
+ SeqMemPointerRecordEx(address addr, MEMFLAGS flags, size_t size,
+ address pc): MemPointerRecordEx(addr, flags, size, pc) {
+ _seq = SequenceGenerator::next();
+ }
+
+ SeqMemPointerRecordEx(const SeqMemPointerRecordEx& copy_from)
+ : MemPointerRecordEx(copy_from) {
+ _seq = copy_from.seq();
+ }
+
+ SeqMemPointerRecordEx& operator= (const SeqMemPointerRecordEx& ptr) {
+ MemPointerRecordEx::operator=(ptr);
+ _seq = ptr.seq();
+ return *this;
+ }
+
+ inline jint seq() const {
+ return _seq;
+ }
+};
+
+#endif // SHARE_VM_SERVICES_MEM_PTR_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memPtrArray.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+#ifndef SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP
+#define SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP
+
+#include "memory/allocation.hpp"
+#include "services/memPtr.hpp"
+
+class MemPtr;
+class MemRecorder;
+class ArenaInfo;
+class MemSnapshot;
+
+extern "C" {
+ typedef int (*FN_SORT)(const void *, const void *);
+}
+
+
+// Memory pointer array interface. This array is used by NMT to hold
+// various memory block information.
+// The memory pointer arrays are usually walked with their iterators.
+
+class MemPointerArray : public CHeapObj<mtNMT> {
+ public:
+ virtual ~MemPointerArray() { }
+
+ // return true if it can not allocate storage for the data
+ virtual bool out_of_memory() const = 0;
+ virtual bool is_empty() const = 0;
+ virtual bool is_full() = 0;
+ virtual int length() const = 0;
+ virtual void clear() = 0;
+ virtual bool append(MemPointer* ptr) = 0;
+ virtual bool insert_at(MemPointer* ptr, int pos) = 0;
+ virtual bool remove_at(int pos) = 0;
+ virtual MemPointer* at(int index) const = 0;
+ virtual void sort(FN_SORT fn) = 0;
+ virtual size_t instance_size() const = 0;
+ virtual bool shrink() = 0;
+
+ debug_only(virtual int capacity() const = 0;)
+};
+
+// Iterator interface
+class MemPointerArrayIterator VALUE_OBJ_CLASS_SPEC {
+ public:
+ // return the pointer at current position
+ virtual MemPointer* current() const = 0;
+ // return the next pointer and advance current position
+ virtual MemPointer* next() = 0;
+ // return next pointer without advancing current position
+ virtual MemPointer* peek_next() const = 0;
+ // return previous pointer without changing current position
+ virtual MemPointer* peek_prev() const = 0;
+ // remove the pointer at current position
+ virtual void remove() = 0;
+ // insert the pointer at current position
+ virtual bool insert(MemPointer* ptr) = 0;
+ // insert specified element after current position and
+ // move current position to newly inserted position
+ virtual bool insert_after(MemPointer* ptr) = 0;
+};
+
+// implementation class
+class MemPointerArrayIteratorImpl : public MemPointerArrayIterator {
+#ifdef ASSERT
+ protected:
+#else
+ private:
+#endif
+ MemPointerArray* _array;
+ int _pos;
+
+ public:
+ MemPointerArrayIteratorImpl(MemPointerArray* arr) {
+ assert(arr != NULL, "Parameter check");
+ _array = arr;
+ _pos = 0;
+ }
+
+ virtual MemPointer* current() const {
+ if (_pos < _array->length()) {
+ return _array->at(_pos);
+ }
+ return NULL;
+ }
+
+ virtual MemPointer* next() {
+ if (_pos + 1 < _array->length()) {
+ return _array->at(++_pos);
+ }
+ _pos = _array->length();
+ return NULL;
+ }
+
+ virtual MemPointer* peek_next() const {
+ if (_pos + 1 < _array->length()) {
+ return _array->at(_pos + 1);
+ }
+ return NULL;
+ }
+
+ virtual MemPointer* peek_prev() const {
+ if (_pos > 0) {
+ return _array->at(_pos - 1);
+ }
+ return NULL;
+ }
+
+ virtual void remove() {
+ if (_pos < _array->length()) {
+ _array->remove_at(_pos);
+ }
+ }
+
+ virtual bool insert(MemPointer* ptr) {
+ return _array->insert_at(ptr, _pos);
+ }
+
+ virtual bool insert_after(MemPointer* ptr) {
+ if (_array->insert_at(ptr, _pos + 1)) {
+ _pos ++;
+ return true;
+ }
+ return false;
+ }
+};
+
+
+
+// Memory pointer array implementation.
+// This implementation implements expandable array
+#define DEFAULT_PTR_ARRAY_SIZE 1024
+
+template <class E> class MemPointerArrayImpl : public MemPointerArray {
+ private:
+ int _max_size;
+ int _size;
+ bool _init_elements;
+ E* _data;
+
+ public:
+ MemPointerArrayImpl(int initial_size = DEFAULT_PTR_ARRAY_SIZE, bool init_elements = true):
+ _max_size(initial_size), _size(0), _init_elements(init_elements) {
+ _data = (E*)raw_allocate(sizeof(E), initial_size);
+ if (_init_elements) {
+ for (int index = 0; index < _max_size; index ++) {
+ ::new ((void*)&_data[index]) E();
+ }
+ }
+ }
+
+ virtual ~MemPointerArrayImpl() {
+ if (_data != NULL) {
+ raw_free(_data);
+ }
+ }
+
+ public:
+ bool out_of_memory() const {
+ return (_data == NULL);
+ }
+
+ size_t instance_size() const {
+ return sizeof(MemPointerArrayImpl<E>) + _max_size * sizeof(E);
+ }
+
+ bool is_empty() const {
+ assert(_data != NULL, "Just check");
+ return _size == 0;
+ }
+
+ bool is_full() {
+ assert(_data != NULL, "Just check");
+ if (_size < _max_size) {
+ return false;
+ } else {
+ return !expand_array();
+ }
+ }
+
+ int length() const {
+ assert(_data != NULL, "Just check");
+ return _size;
+ }
+
+ debug_only(int capacity() const { return _max_size; })
+
+ void clear() {
+ assert(_data != NULL, "Just check");
+ _size = 0;
+ }
+
+ bool append(MemPointer* ptr) {
+ assert(_data != NULL, "Just check");
+ if (is_full()) {
+ return false;
+ }
+ _data[_size ++] = *(E*)ptr;
+ return true;
+ }
+
+ bool insert_at(MemPointer* ptr, int pos) {
+ assert(_data != NULL, "Just check");
+ if (is_full()) {
+ return false;
+ }
+ for (int index = _size; index > pos; index --) {
+ _data[index] = _data[index - 1];
+ }
+ _data[pos] = *(E*)ptr;
+ _size ++;
+ return true;
+ }
+
+ bool remove_at(int pos) {
+ assert(_data != NULL, "Just check");
+ if (_size <= pos && pos >= 0) {
+ return false;
+ }
+ -- _size;
+
+ for (int index = pos; index < _size; index ++) {
+ _data[index] = _data[index + 1];
+ }
+ return true;
+ }
+
+ MemPointer* at(int index) const {
+ assert(_data != NULL, "Just check");
+ assert(index >= 0 && index < _size, "illegal index");
+ return &_data[index];
+ }
+
+ bool shrink() {
+ float used = ((float)_size) / ((float)_max_size);
+ if (used < 0.40) {
+ E* old_ptr = _data;
+ int new_size = ((_max_size) / (2 * DEFAULT_PTR_ARRAY_SIZE) + 1) * DEFAULT_PTR_ARRAY_SIZE;
+ _data = (E*)raw_reallocate(_data, sizeof(E), new_size);
+ if (_data == NULL) {
+ _data = old_ptr;
+ return false;
+ } else {
+ _max_size = new_size;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ void sort(FN_SORT fn) {
+ assert(_data != NULL, "Just check");
+ qsort((void*)_data, _size, sizeof(E), fn);
+ }
+
+ private:
+ bool expand_array() {
+ assert(_data != NULL, "Not yet allocated");
+ E* old_ptr = _data;
+ if ((_data = (E*)raw_reallocate((void*)_data, sizeof(E),
+ _max_size + DEFAULT_PTR_ARRAY_SIZE)) == NULL) {
+ _data = old_ptr;
+ return false;
+ } else {
+ _max_size += DEFAULT_PTR_ARRAY_SIZE;
+ if (_init_elements) {
+ for (int index = _size; index < _max_size; index ++) {
+ ::new ((void*)&_data[index]) E();
+ }
+ }
+ return true;
+ }
+ }
+
+ void* raw_allocate(size_t elementSize, int items) {
+ return os::malloc(elementSize * items, mtNMT);
+ }
+
+ void* raw_reallocate(void* ptr, size_t elementSize, int items) {
+ return os::realloc(ptr, elementSize * items, mtNMT);
+ }
+
+ void raw_free(void* ptr) {
+ os::free(ptr, mtNMT);
+ }
+};
+
+#endif // SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memRecorder.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "runtime/atomic.hpp"
+#include "services/memBaseline.hpp"
+#include "services/memRecorder.hpp"
+#include "services/memPtr.hpp"
+#include "services/memTracker.hpp"
+
+MemPointer* SequencedRecordIterator::next_record() {
+ MemPointer* itr_cur = _itr.current();
+ if (itr_cur == NULL) return NULL;
+ MemPointer* itr_next = _itr.next();
+
+ while (itr_next != NULL &&
+ same_kind((MemPointerRecord*)itr_cur, (MemPointerRecord*)itr_next)) {
+ itr_cur = itr_next;
+ itr_next = _itr.next();
+ }
+
+ return itr_cur;
+}
+
+
+debug_only(volatile jint MemRecorder::_instance_count = 0;)
+
+MemRecorder::MemRecorder() {
+ assert(MemTracker::is_on(), "Native memory tracking is off");
+ debug_only(Atomic::inc(&_instance_count);)
+ debug_only(set_generation();)
+
+ if (MemTracker::track_callsite()) {
+ _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecordEx,
+ DEFAULT_RECORDER_PTR_ARRAY_SIZE>();
+ } else {
+ _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecord,
+ DEFAULT_RECORDER_PTR_ARRAY_SIZE>();
+ }
+ _next = NULL;
+
+
+ if (_pointer_records != NULL) {
+ // recode itself
+ record((address)this, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder),
+ sizeof(MemRecorder), CALLER_PC);
+ record((address)_pointer_records, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder),
+ _pointer_records->instance_size(),CURRENT_PC);
+ }
+}
+
+MemRecorder::~MemRecorder() {
+ if (_pointer_records != NULL) {
+ if (MemTracker::is_on()) {
+ MemTracker::record_free((address)_pointer_records, mtNMT);
+ MemTracker::record_free((address)this, mtNMT);
+ }
+ delete _pointer_records;
+ }
+ if (_next != NULL) {
+ delete _next;
+ }
+
+#ifdef ASSERT
+ Atomic::dec(&_instance_count);
+#endif
+}
+
+// Sorting order:
+// 1. memory block address
+// 2. mem pointer record tags
+// 3. sequence number
+int MemRecorder::sort_record_fn(const void* e1, const void* e2) {
+ const MemPointerRecord* p1 = (const MemPointerRecord*)e1;
+ const MemPointerRecord* p2 = (const MemPointerRecord*)e2;
+ int delta = UNSIGNED_COMPARE(p1->addr(), p2->addr());
+ if (delta == 0) {
+ int df = UNSIGNED_COMPARE((p1->flags() & MemPointerRecord::tag_masks),
+ (p2->flags() & MemPointerRecord::tag_masks));
+ if (df == 0) {
+ assert(p1->seq() != p2->seq(), "dup seq");
+ return p1->seq() - p2->seq();
+ } else {
+ return df;
+ }
+ } else {
+ return delta;
+ }
+}
+
+bool MemRecorder::record(address p, MEMFLAGS flags, size_t size, address pc) {
+#ifdef ASSERT
+ if (MemPointerRecord::is_virtual_memory_record(flags)) {
+ assert((flags & MemPointerRecord::tag_masks) != 0, "bad virtual memory record");
+ } else {
+ assert((flags & MemPointerRecord::tag_masks) == MemPointerRecord::malloc_tag() ||
+ (flags & MemPointerRecord::tag_masks) == MemPointerRecord::free_tag() ||
+ IS_ARENA_OBJ(flags),
+ "bad malloc record");
+ }
+ // a recorder should only hold records within the same generation
+ unsigned long cur_generation = SequenceGenerator::current_generation();
+ assert(cur_generation == _generation,
+ "this thread did not enter sync point");
+#endif
+
+ if (MemTracker::track_callsite()) {
+ SeqMemPointerRecordEx ap(p, flags, size, pc);
+ debug_only(check_dup_seq(ap.seq());)
+ return _pointer_records->append(&ap);
+ } else {
+ SeqMemPointerRecord ap(p, flags, size);
+ debug_only(check_dup_seq(ap.seq());)
+ return _pointer_records->append(&ap);
+ }
+}
+
+ // iterator for alloc pointers
+SequencedRecordIterator MemRecorder::pointer_itr() {
+ assert(_pointer_records != NULL, "just check");
+ _pointer_records->sort((FN_SORT)sort_record_fn);
+ return SequencedRecordIterator(_pointer_records);
+}
+
+
+#ifdef ASSERT
+void MemRecorder::set_generation() {
+ _generation = SequenceGenerator::current_generation();
+}
+
+void MemRecorder::check_dup_seq(jint seq) const {
+ MemPointerArrayIteratorImpl itr(_pointer_records);
+ MemPointerRecord* rc = (MemPointerRecord*)itr.current();
+ while (rc != NULL) {
+ assert(rc->seq() != seq, "dup seq");
+ rc = (MemPointerRecord*)itr.next();
+ }
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memRecorder.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,267 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_MEM_RECORDER_HPP
+#define SHARE_VM_SERVICES_MEM_RECORDER_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/os.hpp"
+#include "services/memPtrArray.hpp"
+
+class MemSnapshot;
+class MemTracker;
+class MemTrackWorker;
+
+// Fixed size memory pointer array implementation
+template <class E, int SIZE> class FixedSizeMemPointerArray :
+ public MemPointerArray {
+ // This implementation is for memory recorder only
+ friend class MemRecorder;
+
+ private:
+ E _data[SIZE];
+ int _size;
+
+ protected:
+ FixedSizeMemPointerArray(bool init_elements = false):
+ _size(0){
+ if (init_elements) {
+ for (int index = 0; index < SIZE; index ++) {
+ ::new ((void*)&_data[index]) E();
+ }
+ }
+ }
+
+ void* operator new(size_t size, const std::nothrow_t& nothrow_constant) {
+ // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder'
+ // to avoid recursion
+ return os::malloc(size, (mtNMT | otNMTRecorder));
+ }
+
+ void* operator new(size_t size) {
+ assert(false, "use nothrow version");
+ return NULL;
+ }
+
+ void operator delete(void* p) {
+ os::free(p, (mtNMT | otNMTRecorder));
+ }
+
+ // instance size
+ inline size_t instance_size() const {
+ return sizeof(FixedSizeMemPointerArray<E, SIZE>);
+ }
+
+ debug_only(int capacity() const { return SIZE; })
+
+ public:
+ // implementation of public interface
+ bool out_of_memory() const { return false; }
+ bool is_empty() const { return _size == 0; }
+ bool is_full() { return length() >= SIZE; }
+ int length() const { return _size; }
+
+ void clear() {
+ _size = 0;
+ }
+
+ bool append(MemPointer* ptr) {
+ if (is_full()) return false;
+ _data[_size ++] = *(E*)ptr;
+ return true;
+ }
+
+ virtual bool insert_at(MemPointer* p, int pos) {
+ assert(false, "append only");
+ return false;
+ }
+
+ virtual bool remove_at(int pos) {
+ assert(false, "not supported");
+ return false;
+ }
+
+ MemPointer* at(int index) const {
+ assert(index >= 0 && index < length(),
+ "parameter check");
+ return ((E*)&_data[index]);
+ }
+
+ void sort(FN_SORT fn) {
+ qsort((void*)_data, _size, sizeof(E), fn);
+ }
+
+ bool shrink() {
+ return false;
+ }
+};
+
+
+// This iterator requires pre-sorted MemPointerArray, which is sorted by:
+// 1. address
+// 2. allocation type
+// 3. sequence number
+// During the array walking, iterator collapses pointers with the same
+// address and allocation type, and only returns the one with highest
+// sequence number.
+//
+// This is read-only iterator, update methods are asserted.
+class SequencedRecordIterator : public MemPointerArrayIterator {
+ private:
+ MemPointerArrayIteratorImpl _itr;
+ MemPointer* _cur;
+
+ public:
+ SequencedRecordIterator(const MemPointerArray* arr):
+ _itr(const_cast<MemPointerArray*>(arr)) {
+ _cur = next_record();
+ }
+
+ SequencedRecordIterator(const SequencedRecordIterator& itr):
+ _itr(itr._itr) {
+ _cur = next_record();
+ }
+
+ // return the pointer at current position
+ virtual MemPointer* current() const {
+ return _cur;
+ };
+
+ // return the next pointer and advance current position
+ virtual MemPointer* next() {
+ _cur = next_record();
+ return _cur;
+ }
+
+ // return the next pointer without advancing current position
+ virtual MemPointer* peek_next() const {
+ assert(false, "not implemented");
+ return NULL;
+
+ }
+ // return the previous pointer without changing current position
+ virtual MemPointer* peek_prev() const {
+ assert(false, "not implemented");
+ return NULL;
+ }
+
+ // remove the pointer at current position
+ virtual void remove() {
+ assert(false, "read-only iterator");
+ };
+ // insert the pointer at current position
+ virtual bool insert(MemPointer* ptr) {
+ assert(false, "read-only iterator");
+ return false;
+ }
+
+ virtual bool insert_after(MemPointer* ptr) {
+ assert(false, "read-only iterator");
+ return false;
+ }
+ private:
+ // collapse the 'same kind' of records, and return this 'kind' of
+ // record with highest sequence number
+ MemPointer* next_record();
+
+ // Test if the two records are the same kind: the same memory block and allocation
+ // type.
+ inline bool same_kind(const MemPointerRecord* p1, const MemPointerRecord* p2) const {
+ return (p1->addr() == p2->addr() &&
+ (p1->flags() &MemPointerRecord::tag_masks) ==
+ (p2->flags() & MemPointerRecord::tag_masks));
+ }
+};
+
+
+
+#define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512
+
+class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
+ friend class MemSnapshot;
+ friend class MemTracker;
+ friend class MemTrackWorker;
+
+ protected:
+ // the array that holds memory records
+ MemPointerArray* _pointer_records;
+
+ private:
+ // used for linked list
+ MemRecorder* _next;
+ // active recorder can only record a certain generation data
+ debug_only(unsigned long _generation;)
+
+ protected:
+ _NOINLINE_ MemRecorder();
+ ~MemRecorder();
+
+ // record a memory operation
+ bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0);
+
+ // linked list support
+ inline void set_next(MemRecorder* rec) {
+ _next = rec;
+ }
+
+ inline MemRecorder* next() const {
+ return _next;
+ }
+
+ // if the recorder is full
+ inline bool is_full() const {
+ assert(_pointer_records != NULL, "just check");
+ return _pointer_records->is_full();
+ }
+
+ // if running out of memory when initializing recorder's internal
+ // data
+ inline bool out_of_memory() const {
+ return (_pointer_records == NULL ||
+ _pointer_records->out_of_memory());
+ }
+
+ inline void clear() {
+ assert(_pointer_records != NULL, "Just check");
+ _pointer_records->clear();
+ }
+
+ SequencedRecordIterator pointer_itr();
+
+ public:
+ // number of MemRecorder instance
+ debug_only(static volatile jint _instance_count;)
+
+ private:
+ // sorting function, sort records into following order
+ // 1. memory address
+ // 2. allocation type
+ // 3. sequence number
+ static int sort_record_fn(const void* e1, const void* e2);
+
+ debug_only(void check_dup_seq(jint seq) const;)
+ debug_only(void set_generation();)
+};
+
+#endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memReporter.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,560 @@
+/*
+ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "runtime/os.hpp"
+#include "services/memReporter.hpp"
+#include "services/memPtrArray.hpp"
+#include "services/memTracker.hpp"
+
+const char* BaselineOutputer::memory_unit(size_t scale) {
+ switch(scale) {
+ case K: return "KB";
+ case M: return "MB";
+ case G: return "GB";
+ }
+ ShouldNotReachHere();
+ return NULL;
+}
+
+
+void BaselineReporter::report_baseline(const MemBaseline& baseline, bool summary_only) {
+ assert(MemTracker::is_on(), "Native memory tracking is off");
+ _outputer.start(scale());
+ _outputer.total_usage(
+ amount_in_current_scale(baseline.total_malloc_amount() + baseline.total_reserved_amount()),
+ amount_in_current_scale(baseline.total_malloc_amount() + baseline.total_committed_amount()));
+
+ _outputer.num_of_classes(baseline.number_of_classes());
+ _outputer.num_of_threads(baseline.number_of_threads());
+
+ report_summaries(baseline);
+ if (!summary_only && MemTracker::track_callsite()) {
+ report_callsites(baseline);
+ }
+ _outputer.done();
+}
+
+void BaselineReporter::report_summaries(const MemBaseline& baseline) {
+ _outputer.start_category_summary();
+ MEMFLAGS type;
+
+ for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
+ type = MemBaseline::MemType2NameMap[index]._flag;
+ _outputer.category_summary(type,
+ amount_in_current_scale(baseline.reserved_amount(type)),
+ amount_in_current_scale(baseline.committed_amount(type)),
+ amount_in_current_scale(baseline.malloc_amount(type)),
+ baseline.malloc_count(type),
+ amount_in_current_scale(baseline.arena_amount(type)),
+ baseline.arena_count(type));
+ }
+
+ _outputer.done_category_summary();
+}
+
+void BaselineReporter::report_callsites(const MemBaseline& baseline) {
+ _outputer.start_callsite();
+ MemBaseline* pBL = const_cast<MemBaseline*>(&baseline);
+
+ pBL->_malloc_cs->sort((FN_SORT)MemBaseline::bl_malloc_sort_by_size);
+ pBL->_vm_cs->sort((FN_SORT)MemBaseline::bl_vm_sort_by_size);
+
+ // walk malloc callsites
+ MemPointerArrayIteratorImpl malloc_itr(pBL->_malloc_cs);
+ MallocCallsitePointer* malloc_callsite =
+ (MallocCallsitePointer*)malloc_itr.current();
+ while (malloc_callsite != NULL) {
+ _outputer.malloc_callsite(malloc_callsite->addr(),
+ amount_in_current_scale(malloc_callsite->amount()), malloc_callsite->count());
+ malloc_callsite = (MallocCallsitePointer*)malloc_itr.next();
+ }
+
+ // walk virtual memory callsite
+ MemPointerArrayIteratorImpl vm_itr(pBL->_vm_cs);
+ VMCallsitePointer* vm_callsite = (VMCallsitePointer*)vm_itr.current();
+ while (vm_callsite != NULL) {
+ _outputer.virtual_memory_callsite(vm_callsite->addr(),
+ amount_in_current_scale(vm_callsite->reserved_amount()),
+ amount_in_current_scale(vm_callsite->committed_amount()));
+ vm_callsite = (VMCallsitePointer*)vm_itr.next();
+ }
+ pBL->_malloc_cs->sort((FN_SORT)MemBaseline::bl_malloc_sort_by_pc);
+ pBL->_vm_cs->sort((FN_SORT)MemBaseline::bl_vm_sort_by_pc);
+ _outputer.done_callsite();
+}
+
+void BaselineReporter::diff_baselines(const MemBaseline& cur, const MemBaseline& prev,
+ bool summary_only) {
+ assert(MemTracker::is_on(), "Native memory tracking is off");
+ _outputer.start(scale());
+ size_t total_reserved = cur.total_malloc_amount() + cur.total_reserved_amount();
+ size_t total_committed = cur.total_malloc_amount() + cur.total_committed_amount();
+
+ _outputer.diff_total_usage(
+ amount_in_current_scale(total_reserved), amount_in_current_scale(total_committed),
+ diff_in_current_scale(total_reserved, (prev.total_malloc_amount() + prev.total_reserved_amount())),
+ diff_in_current_scale(total_committed, (prev.total_committed_amount() + prev.total_malloc_amount())));
+
+ _outputer.diff_num_of_classes(cur.number_of_classes(),
+ diff(cur.number_of_classes(), prev.number_of_classes()));
+ _outputer.diff_num_of_threads(cur.number_of_threads(),
+ diff(cur.number_of_threads(), prev.number_of_threads()));
+
+ diff_summaries(cur, prev);
+ if (!summary_only && MemTracker::track_callsite()) {
+ diff_callsites(cur, prev);
+ }
+ _outputer.done();
+}
+
+void BaselineReporter::diff_summaries(const MemBaseline& cur, const MemBaseline& prev) {
+ _outputer.start_category_summary();
+ MEMFLAGS type;
+
+ for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
+ type = MemBaseline::MemType2NameMap[index]._flag;
+ _outputer.diff_category_summary(type,
+ amount_in_current_scale(cur.reserved_amount(type)),
+ amount_in_current_scale(cur.committed_amount(type)),
+ amount_in_current_scale(cur.malloc_amount(type)),
+ cur.malloc_count(type),
+ amount_in_current_scale(cur.arena_amount(type)),
+ cur.arena_count(type),
+ diff_in_current_scale(cur.reserved_amount(type), prev.reserved_amount(type)),
+ diff_in_current_scale(cur.committed_amount(type), prev.committed_amount(type)),
+ diff_in_current_scale(cur.malloc_amount(type), prev.malloc_amount(type)),
+ diff(cur.malloc_count(type), prev.malloc_count(type)),
+ diff_in_current_scale(cur.arena_amount(type), prev.arena_amount(type)),
+ diff(cur.arena_count(type), prev.arena_count(type)));
+ }
+
+ _outputer.done_category_summary();
+}
+
+void BaselineReporter::diff_callsites(const MemBaseline& cur, const MemBaseline& prev) {
+ _outputer.start_callsite();
+ MemBaseline* pBL_cur = const_cast<MemBaseline*>(&cur);
+ MemBaseline* pBL_prev = const_cast<MemBaseline*>(&prev);
+
+ // walk malloc callsites
+ MemPointerArrayIteratorImpl cur_malloc_itr(pBL_cur->_malloc_cs);
+ MemPointerArrayIteratorImpl prev_malloc_itr(pBL_prev->_malloc_cs);
+
+ MallocCallsitePointer* cur_malloc_callsite =
+ (MallocCallsitePointer*)cur_malloc_itr.current();
+ MallocCallsitePointer* prev_malloc_callsite =
+ (MallocCallsitePointer*)prev_malloc_itr.current();
+
+ while (cur_malloc_callsite != NULL || prev_malloc_callsite != NULL) {
+ if (prev_malloc_callsite == NULL ||
+ cur_malloc_callsite->addr() < prev_malloc_callsite->addr()) {
+ _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
+ amount_in_current_scale(cur_malloc_callsite->amount()),
+ cur_malloc_callsite->count(),
+ diff_in_current_scale(cur_malloc_callsite->amount(), 0),
+ diff(cur_malloc_callsite->count(), 0));
+ cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next();
+ } else if (prev_malloc_callsite == NULL ||
+ cur_malloc_callsite->addr() > prev_malloc_callsite->addr()) {
+ _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
+ amount_in_current_scale(prev_malloc_callsite->amount()),
+ prev_malloc_callsite->count(),
+ diff_in_current_scale(0, prev_malloc_callsite->amount()),
+ diff(0, prev_malloc_callsite->count()));
+ prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next();
+ } else { // the same callsite
+ _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
+ amount_in_current_scale(cur_malloc_callsite->amount()),
+ cur_malloc_callsite->count(),
+ diff_in_current_scale(cur_malloc_callsite->amount(), prev_malloc_callsite->amount()),
+ diff(cur_malloc_callsite->count(), prev_malloc_callsite->count()));
+ cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next();
+ prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next();
+ }
+ }
+
+ // walk virtual memory callsite
+ MemPointerArrayIteratorImpl cur_vm_itr(pBL_cur->_vm_cs);
+ MemPointerArrayIteratorImpl prev_vm_itr(pBL_prev->_vm_cs);
+ VMCallsitePointer* cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.current();
+ VMCallsitePointer* prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.current();
+ while (cur_vm_callsite != NULL || prev_vm_callsite != NULL) {
+ if (prev_vm_callsite == NULL || cur_vm_callsite->addr() < prev_vm_callsite->addr()) {
+ _outputer.diff_virtual_memory_callsite(cur_vm_callsite->addr(),
+ amount_in_current_scale(cur_vm_callsite->reserved_amount()),
+ amount_in_current_scale(cur_vm_callsite->committed_amount()),
+ diff_in_current_scale(cur_vm_callsite->reserved_amount(), 0),
+ diff_in_current_scale(cur_vm_callsite->committed_amount(), 0));
+ cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.next();
+ } else if (cur_vm_callsite == NULL || cur_vm_callsite->addr() > prev_vm_callsite->addr()) {
+ _outputer.diff_virtual_memory_callsite(prev_vm_callsite->addr(),
+ amount_in_current_scale(prev_vm_callsite->reserved_amount()),
+ amount_in_current_scale(prev_vm_callsite->committed_amount()),
+ diff_in_current_scale(0, prev_vm_callsite->reserved_amount()),
+ diff_in_current_scale(0, prev_vm_callsite->committed_amount()));
+ prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.next();
+ } else { // the same callsite
+ _outputer.diff_virtual_memory_callsite(cur_vm_callsite->addr(),
+ amount_in_current_scale(cur_vm_callsite->reserved_amount()),
+ amount_in_current_scale(cur_vm_callsite->committed_amount()),
+ diff_in_current_scale(cur_vm_callsite->reserved_amount(), prev_vm_callsite->reserved_amount()),
+ diff_in_current_scale(cur_vm_callsite->committed_amount(), prev_vm_callsite->committed_amount()));
+ cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.next();
+ prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.next();
+ }
+ }
+
+ _outputer.done_callsite();
+}
+
+size_t BaselineReporter::amount_in_current_scale(size_t amt) const {
+ return (size_t)(((float)amt/(float)_scale) + 0.5);
+}
+
+int BaselineReporter::diff_in_current_scale(size_t value1, size_t value2) const {
+ return (int)(((float)value1 - (float)value2)/((float)_scale) + 0.5);
+}
+
+int BaselineReporter::diff(size_t value1, size_t value2) const {
+ return ((int)value1 - (int)value2);
+}
+
+void BaselineTTYOutputer::start(size_t scale, bool report_diff) {
+ _scale = scale;
+ _output->print_cr(" ");
+ _output->print_cr("Native Memory Tracking:");
+ _output->print_cr(" ");
+}
+
+void BaselineTTYOutputer::done() {
+
+}
+
+void BaselineTTYOutputer::total_usage(size_t total_reserved, size_t total_committed) {
+ const char* unit = memory_unit(_scale);
+ _output->print_cr("Total: reserved=%d%s, committed=%d%s",
+ total_reserved, unit, total_committed, unit);
+}
+
+void BaselineTTYOutputer::start_category_summary() {
+ _output->print_cr(" ");
+}
+
+/**
+ * report a summary of memory type
+ */
+void BaselineTTYOutputer::category_summary(MEMFLAGS type,
+ size_t reserved_amt, size_t committed_amt, size_t malloc_amt,
+ size_t malloc_count, size_t arena_amt, size_t arena_count) {
+
+ // we report mtThreadStack under mtThread category
+ if (type == mtThreadStack) {
+ assert(malloc_amt == 0 && malloc_count == 0 && arena_amt == 0,
+ "Just check");
+ _thread_stack_reserved = reserved_amt;
+ _thread_stack_committed = committed_amt;
+ } else {
+ const char* unit = memory_unit(_scale);
+ size_t total_reserved = (reserved_amt + malloc_amt + arena_amt);
+ size_t total_committed = (committed_amt + malloc_amt + arena_amt);
+ if (type == mtThread) {
+ total_reserved += _thread_stack_reserved;
+ total_committed += _thread_stack_committed;
+ }
+
+ if (total_reserved > 0) {
+ _output->print_cr("-%26s (reserved=%d%s, committed=%d%s)",
+ MemBaseline::type2name(type), total_reserved, unit,
+ total_committed, unit);
+
+ if (type == mtClass) {
+ _output->print_cr("%27s (classes #%d)", " ", _num_of_classes);
+ } else if (type == mtThread) {
+ _output->print_cr("%27s (thread #%d)", " ", _num_of_threads);
+ _output->print_cr("%27s (stack: reserved=%d%s, committed=%d%s)", " ",
+ _thread_stack_reserved, unit, _thread_stack_committed, unit);
+ }
+
+ if (malloc_amt > 0) {
+ if (type != mtChunk) {
+ _output->print_cr("%27s (malloc=%d%s, #%d)", " ", malloc_amt, unit,
+ malloc_count);
+ } else {
+ _output->print_cr("%27s (malloc=%d%s)", " ", malloc_amt, unit);
+ }
+ }
+
+ if (reserved_amt > 0) {
+ _output->print_cr("%27s (mmap: reserved=%d%s, committed=%d%s)",
+ " ", reserved_amt, unit, committed_amt, unit);
+ }
+
+ if (arena_amt > 0) {
+ _output->print_cr("%27s (arena=%d%s, #%d)", " ", arena_amt, unit, arena_count);
+ }
+
+ _output->print_cr(" ");
+ }
+ }
+}
+
+void BaselineTTYOutputer::done_category_summary() {
+ _output->print_cr(" ");
+}
+
+void BaselineTTYOutputer::start_callsite() {
+ _output->print_cr("Details:");
+ _output->print_cr(" ");
+}
+
+void BaselineTTYOutputer::done_callsite() {
+ _output->print_cr(" ");
+}
+
+void BaselineTTYOutputer::malloc_callsite(address pc, size_t malloc_amt,
+ size_t malloc_count) {
+ if (malloc_amt > 0) {
+ const char* unit = memory_unit(_scale);
+ char buf[64];
+ int offset;
+ if (pc == 0) {
+ _output->print("[BOOTSTRAP]%18s", " ");
+ } else if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
+ _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
+ _output->print("%28s", " ");
+ } else {
+ _output->print("[" PTR_FORMAT "]%18s", pc, " ");
+ }
+
+ _output->print_cr("(malloc=%d%s #%d)", malloc_amt, unit, malloc_count);
+ _output->print_cr(" ");
+ }
+}
+
+void BaselineTTYOutputer::virtual_memory_callsite(address pc, size_t reserved_amt,
+ size_t committed_amt) {
+ if (reserved_amt > 0) {
+ const char* unit = memory_unit(_scale);
+ char buf[64];
+ int offset;
+ if (pc == 0) {
+ _output->print("[BOOTSTRAP]%18s", " ");
+ } else if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
+ _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
+ _output->print("%28s", " ");
+ } else {
+ _output->print("[" PTR_FORMAT "]%18s", " ");
+ }
+
+ _output->print_cr("(mmap: reserved=%d%s, committed=%d%s)",
+ reserved_amt, unit, committed_amt, unit);
+ _output->print_cr(" ");
+ }
+}
+
+void BaselineTTYOutputer::diff_total_usage(size_t total_reserved,
+ size_t total_committed, int reserved_diff, int committed_diff) {
+ const char* unit = memory_unit(_scale);
+ _output->print_cr("Total: reserved=%d%s %+d%s, committed=%d%s %+d%s",
+ total_reserved, unit, reserved_diff, unit, total_committed, unit,
+ committed_diff, unit);
+}
+
+void BaselineTTYOutputer::diff_category_summary(MEMFLAGS type,
+ size_t cur_reserved_amt, size_t cur_committed_amt,
+ size_t cur_malloc_amt, size_t cur_malloc_count,
+ size_t cur_arena_amt, size_t cur_arena_count,
+ int reserved_diff, int committed_diff, int malloc_diff,
+ int malloc_count_diff, int arena_diff, int arena_count_diff) {
+
+ if (type == mtThreadStack) {
+ assert(cur_malloc_amt == 0 && cur_malloc_count == 0 &&
+ cur_arena_amt == 0, "Just check");
+ _thread_stack_reserved = cur_reserved_amt;
+ _thread_stack_committed = cur_committed_amt;
+ _thread_stack_reserved_diff = reserved_diff;
+ _thread_stack_committed_diff = committed_diff;
+ } else {
+ const char* unit = memory_unit(_scale);
+ size_t total_reserved = (cur_reserved_amt + cur_malloc_amt + cur_arena_amt);
+ // nothing to report in this category
+ if (total_reserved == 0) {
+ return;
+ }
+ int diff_reserved = (reserved_diff + malloc_diff + arena_diff);
+
+ // category summary
+ _output->print("-%26s (reserved=%d%s", MemBaseline::type2name(type),
+ total_reserved, unit);
+
+ if (diff_reserved != 0) {
+ _output->print(" %+d%s", diff_reserved, unit);
+ }
+
+ size_t total_committed = cur_committed_amt + cur_malloc_amt + cur_arena_amt;
+ _output->print(", committed=%d%s", total_committed, unit);
+
+ int total_committed_diff = committed_diff + malloc_diff + arena_diff;
+ if (total_committed_diff != 0) {
+ _output->print(" %+d%s", total_committed_diff, unit);
+ }
+
+ _output->print_cr(")");
+
+ // special cases
+ if (type == mtClass) {
+ _output->print("%27s (classes #%d", " ", _num_of_classes);
+ if (_num_of_classes_diff != 0) {
+ _output->print(" %+d", _num_of_classes_diff);
+ }
+ _output->print_cr(")");
+ } else if (type == mtThread) {
+ // thread count
+ _output->print("%27s (thread #%d", " ", _num_of_threads);
+ if (_num_of_threads_diff != 0) {
+ _output->print_cr(" %+d)", _num_of_threads_diff);
+ } else {
+ _output->print_cr(")");
+ }
+ _output->print("%27s (stack: reserved=%d%s", " ", _thread_stack_reserved, unit);
+ if (_thread_stack_reserved_diff != 0) {
+ _output->print(" %+d%s", _thread_stack_reserved_diff, unit);
+ }
+
+ _output->print(", committed=%d%s", _thread_stack_committed, unit);
+ if (_thread_stack_committed_diff != 0) {
+ _output->print(" %+d%s",_thread_stack_committed_diff, unit);
+ }
+
+ _output->print_cr(")");
+ }
+
+ // malloc'd memory
+ if (cur_malloc_amt > 0) {
+ _output->print("%27s (malloc=%d%s", " ", cur_malloc_amt, unit);
+ if (malloc_diff != 0) {
+ _output->print(" %+d%s", malloc_diff, unit);
+ }
+ if (type != mtChunk) {
+ _output->print(", #%d", cur_malloc_count);
+ if (malloc_count_diff) {
+ _output->print(" %+d", malloc_count_diff);
+ }
+ }
+ _output->print_cr(")");
+ }
+
+ // mmap'd memory
+ if (cur_reserved_amt > 0) {
+ _output->print("%27s (mmap: reserved=%d%s", " ", cur_reserved_amt, unit);
+ if (reserved_diff != 0) {
+ _output->print(" %+d%s", reserved_diff, unit);
+ }
+
+ _output->print(", committed=%d%s", cur_committed_amt, unit);
+ if (committed_diff != 0) {
+ _output->print(" %+d%s", committed_diff, unit);
+ }
+ _output->print_cr(")");
+ }
+
+ // arena memory
+ if (cur_arena_amt > 0) {
+ _output->print("%27s (arena=%d%s", " ", cur_arena_amt, unit);
+ if (arena_diff != 0) {
+ _output->print(" %+d%s", arena_diff, unit);
+ }
+ _output->print(", #%d", cur_arena_count);
+ if (arena_count_diff != 0) {
+ _output->print(" %+d", arena_count_diff);
+ }
+ _output->print_cr(")");
+ }
+
+ _output->print_cr(" ");
+ }
+}
+
+void BaselineTTYOutputer::diff_malloc_callsite(address pc,
+ size_t cur_malloc_amt, size_t cur_malloc_count,
+ int malloc_diff, int malloc_count_diff) {
+ if (malloc_diff != 0) {
+ const char* unit = memory_unit(_scale);
+ char buf[64];
+ int offset;
+ if (pc == 0) {
+ _output->print_cr("[BOOTSTRAP]%18s", " ");
+ } else {
+ if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
+ _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
+ _output->print("%28s", " ");
+ } else {
+ _output->print("[" PTR_FORMAT "]%18s", pc, " ");
+ }
+ }
+
+ _output->print("(malloc=%d%s", cur_malloc_amt, unit);
+ if (malloc_diff != 0) {
+ _output->print(" %+d%s", malloc_diff, unit);
+ }
+ _output->print(", #%d", cur_malloc_count);
+ if (malloc_count_diff != 0) {
+ _output->print(" %+d", malloc_count_diff);
+ }
+ _output->print_cr(")");
+ _output->print_cr(" ");
+ }
+}
+
+void BaselineTTYOutputer::diff_virtual_memory_callsite(address pc,
+ size_t cur_reserved_amt, size_t cur_committed_amt,
+ int reserved_diff, int committed_diff) {
+ if (reserved_diff != 0 || committed_diff != 0) {
+ const char* unit = memory_unit(_scale);
+ char buf[64];
+ int offset;
+ if (pc == 0) {
+ _output->print_cr("[BOOSTRAP]%18s", " ");
+ } else {
+ if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
+ _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
+ _output->print("%28s", " ");
+ } else {
+ _output->print("[" PTR_FORMAT "]%18s", " ");
+ }
+ }
+
+ _output->print("(mmap: reserved=%d%s", cur_reserved_amt, unit);
+ if (reserved_diff != 0) {
+ _output->print(" %+d%s", reserved_diff, unit);
+ }
+ _output->print(", committed=%d%s", cur_committed_amt, unit);
+ if (committed_diff != 0) {
+ _output->print(" %+d%s", committed_diff, unit);
+ }
+ _output->print_cr(")");
+ _output->print_cr(" ");
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memReporter.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,268 @@
+/*
+ * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_MEM_REPORTER_HPP
+#define SHARE_VM_SERVICES_MEM_REPORTER_HPP
+
+#include "runtime/mutexLocker.hpp"
+#include "services/memBaseline.hpp"
+#include "services/memTracker.hpp"
+#include "utilities/ostream.hpp"
+
+/*
+ * MemBaselineReporter reports data to this outputer class,
+ * ReportOutputer is responsible for format, store and redirect
+ * the data to the final destination.
+ */
+class BaselineOutputer : public StackObj {
+ public:
+ // start to report memory usage in specified scale.
+ // if report_diff = true, the reporter reports baseline comparison
+ // information.
+
+ virtual void start(size_t scale, bool report_diff = false) = 0;
+ // Done reporting
+ virtual void done() = 0;
+
+ /* report baseline summary information */
+ virtual void total_usage(size_t total_reserved,
+ size_t total_committed) = 0;
+ virtual void num_of_classes(size_t classes) = 0;
+ virtual void num_of_threads(size_t threads) = 0;
+
+ virtual void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) = 0;
+
+ /* report baseline summary comparison */
+ virtual void diff_total_usage(size_t total_reserved,
+ size_t total_committed,
+ int reserved_diff,
+ int committed_diff) = 0;
+ virtual void diff_num_of_classes(size_t classes, int diff) = 0;
+ virtual void diff_num_of_threads(size_t threads, int diff) = 0;
+
+ virtual void diff_thread_info(size_t stack_reserved, size_t stack_committed,
+ int stack_reserved_diff, int stack_committed_diff) = 0;
+
+
+ /*
+ * memory summary by memory types.
+ * for each memory type, following summaries are reported:
+ * - reserved amount, committed amount
+ * - malloc'd amount, malloc count
+ * - arena amount, arena count
+ */
+
+ // start reporting memory summary by memory type
+ virtual void start_category_summary() = 0;
+
+ virtual void category_summary(MEMFLAGS type, size_t reserved_amt,
+ size_t committed_amt,
+ size_t malloc_amt, size_t malloc_count,
+ size_t arena_amt, size_t arena_count) = 0;
+
+ virtual void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt,
+ size_t cur_committed_amt,
+ size_t cur_malloc_amt, size_t cur_malloc_count,
+ size_t cur_arena_amt, size_t cur_arena_count,
+ int reserved_diff, int committed_diff, int malloc_diff,
+ int malloc_count_diff, int arena_diff,
+ int arena_count_diff) = 0;
+
+ virtual void done_category_summary() = 0;
+
+ /*
+ * Report callsite information
+ */
+ virtual void start_callsite() = 0;
+ virtual void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count) = 0;
+ virtual void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt) = 0;
+
+ virtual void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count,
+ int malloc_diff, int malloc_count_diff) = 0;
+ virtual void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt,
+ int reserved_diff, int committed_diff) = 0;
+
+ virtual void done_callsite() = 0;
+
+ // return current scale in "KB", "MB" or "GB"
+ static const char* memory_unit(size_t scale);
+};
+
+/*
+ * This class reports processed data from a baseline or
+ * the changes between the two baseline.
+ */
+class BaselineReporter : public StackObj {
+ private:
+ BaselineOutputer& _outputer;
+ size_t _scale;
+
+ public:
+ // construct a reporter that reports memory usage
+ // in specified scale
+ BaselineReporter(BaselineOutputer& outputer, size_t scale = K):
+ _outputer(outputer) {
+ _scale = scale;
+ }
+ virtual void report_baseline(const MemBaseline& baseline, bool summary_only = false);
+ virtual void diff_baselines(const MemBaseline& cur, const MemBaseline& prev,
+ bool summary_only = false);
+
+ void set_scale(size_t scale);
+ size_t scale() const { return _scale; }
+
+ private:
+ void report_summaries(const MemBaseline& baseline);
+ void report_callsites(const MemBaseline& baseline);
+
+ void diff_summaries(const MemBaseline& cur, const MemBaseline& prev);
+ void diff_callsites(const MemBaseline& cur, const MemBaseline& prev);
+
+ // calculate memory size in current memory scale
+ size_t amount_in_current_scale(size_t amt) const;
+ // diff two unsigned values in current memory scale
+ int diff_in_current_scale(size_t value1, size_t value2) const;
+ // diff two unsigned value
+ int diff(size_t value1, size_t value2) const;
+};
+
+/*
+ * tty output implementation. Native memory tracking
+ * DCmd uses this outputer.
+ */
+class BaselineTTYOutputer : public BaselineOutputer {
+ private:
+ size_t _scale;
+
+ size_t _num_of_classes;
+ size_t _num_of_threads;
+ size_t _thread_stack_reserved;
+ size_t _thread_stack_committed;
+
+ int _num_of_classes_diff;
+ int _num_of_threads_diff;
+ int _thread_stack_reserved_diff;
+ int _thread_stack_committed_diff;
+
+ outputStream* _output;
+
+ public:
+ BaselineTTYOutputer(outputStream* st) {
+ _scale = K;
+ _num_of_classes = 0;
+ _num_of_threads = 0;
+ _thread_stack_reserved = 0;
+ _thread_stack_committed = 0;
+ _num_of_classes_diff = 0;
+ _num_of_threads_diff = 0;
+ _thread_stack_reserved_diff = 0;
+ _thread_stack_committed_diff = 0;
+ _output = st;
+ }
+
+ // begin reporting memory usage in specified scale
+ void start(size_t scale, bool report_diff = false);
+ // done reporting
+ void done();
+
+ // total memory usage
+ void total_usage(size_t total_reserved,
+ size_t total_committed);
+ // report total loaded classes
+ void num_of_classes(size_t classes) {
+ _num_of_classes = classes;
+ }
+
+ void num_of_threads(size_t threads) {
+ _num_of_threads = threads;
+ }
+
+ void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) {
+ _thread_stack_reserved = stack_reserved_amt;
+ _thread_stack_committed = stack_committed_amt;
+ }
+
+ void diff_total_usage(size_t total_reserved,
+ size_t total_committed,
+ int reserved_diff,
+ int committed_diff);
+
+ void diff_num_of_classes(size_t classes, int diff) {
+ _num_of_classes = classes;
+ _num_of_classes_diff = diff;
+ }
+
+ void diff_num_of_threads(size_t threads, int diff) {
+ _num_of_threads = threads;
+ _num_of_threads_diff = diff;
+ }
+
+ void diff_thread_info(size_t stack_reserved_amt, size_t stack_committed_amt,
+ int stack_reserved_diff, int stack_committed_diff) {
+ _thread_stack_reserved = stack_reserved_amt;
+ _thread_stack_committed = stack_committed_amt;
+ _thread_stack_reserved_diff = stack_reserved_diff;
+ _thread_stack_committed_diff = stack_committed_diff;
+ }
+
+ /*
+ * Report memory summary categoriuzed by memory types.
+ * For each memory type, following summaries are reported:
+ * - reserved amount, committed amount
+ * - malloc-ed amount, malloc count
+ * - arena amount, arena count
+ */
+ // start reporting memory summary by memory type
+ void start_category_summary();
+ void category_summary(MEMFLAGS type, size_t reserved_amt, size_t committed_amt,
+ size_t malloc_amt, size_t malloc_count,
+ size_t arena_amt, size_t arena_count);
+
+ void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt,
+ size_t cur_committed_amt,
+ size_t cur_malloc_amt, size_t cur_malloc_count,
+ size_t cur_arena_amt, size_t cur_arena_count,
+ int reserved_diff, int committed_diff, int malloc_diff,
+ int malloc_count_diff, int arena_diff,
+ int arena_count_diff);
+
+ void done_category_summary();
+
+ /*
+ * Report callsite information
+ */
+ void start_callsite();
+ void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count);
+ void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt);
+
+ void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count,
+ int malloc_diff, int malloc_count_diff);
+ void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt,
+ int reserved_diff, int committed_diff);
+
+ void done_callsite();
+};
+
+
+#endif // SHARE_VM_SERVICES_MEM_REPORTER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memSnapshot.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,463 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "runtime/mutexLocker.hpp"
+#include "utilities/decoder.hpp"
+#include "services/memBaseline.hpp"
+#include "services/memPtr.hpp"
+#include "services/memPtrArray.hpp"
+#include "services/memSnapshot.hpp"
+#include "services/memTracker.hpp"
+
+
+// stagging data groups the data of a VM memory range, so we can consolidate
+// them into one record during the walk
+bool StagingWalker::consolidate_vm_records(VMMemRegionEx* vm_rec) {
+ MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
+ assert(cur != NULL && cur->is_vm_pointer(), "not a virtual memory pointer");
+
+ jint cur_seq;
+ jint next_seq;
+
+ bool trackCallsite = MemTracker::track_callsite();
+
+ if (trackCallsite) {
+ vm_rec->init((MemPointerRecordEx*)cur);
+ cur_seq = ((SeqMemPointerRecordEx*)cur)->seq();
+ } else {
+ vm_rec->init((MemPointerRecord*)cur);
+ cur_seq = ((SeqMemPointerRecord*)cur)->seq();
+ }
+
+ // only can consolidate when we have allocation record,
+ // which contains virtual memory range
+ if (!cur->is_allocation_record()) {
+ _itr.next();
+ return true;
+ }
+
+ // allocation range
+ address base = cur->addr();
+ address end = base + cur->size();
+
+ MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next();
+ // if the memory range is alive
+ bool live_vm_rec = true;
+ while (next != NULL && next->is_vm_pointer()) {
+ if (next->is_allocation_record()) {
+ assert(next->addr() >= base, "sorting order or overlapping");
+ break;
+ }
+
+ if (trackCallsite) {
+ next_seq = ((SeqMemPointerRecordEx*)next)->seq();
+ } else {
+ next_seq = ((SeqMemPointerRecord*)next)->seq();
+ }
+
+ if (next_seq < cur_seq) {
+ _itr.next();
+ next = (MemPointerRecord*)_itr.peek_next();
+ continue;
+ }
+
+ if (next->is_deallocation_record()) {
+ if (next->addr() == base && next->size() == cur->size()) {
+ // the virtual memory range has been released
+ _itr.next();
+ live_vm_rec = false;
+ break;
+ } else if (next->addr() < end) { // partial release
+ vm_rec->partial_release(next->addr(), next->size());
+ _itr.next();
+ } else {
+ break;
+ }
+ } else if (next->is_commit_record()) {
+ if (next->addr() >= base && next->addr() + next->size() <= end) {
+ vm_rec->commit(next->size());
+ _itr.next();
+ } else {
+ assert(next->addr() >= base, "sorting order or overlapping");
+ break;
+ }
+ } else if (next->is_uncommit_record()) {
+ if (next->addr() >= base && next->addr() + next->size() <= end) {
+ vm_rec->uncommit(next->size());
+ _itr.next();
+ } else {
+ assert(next->addr() >= end, "sorting order or overlapping");
+ break;
+ }
+ } else if (next->is_type_tagging_record()) {
+ if (next->addr() >= base && next->addr() < end ) {
+ vm_rec->tag(next->flags());
+ _itr.next();
+ } else {
+ break;
+ }
+ } else {
+ assert(false, "unknown record type");
+ }
+ next = (MemPointerRecord*)_itr.peek_next();
+ }
+ _itr.next();
+ return live_vm_rec;
+}
+
+MemPointer* StagingWalker::next() {
+ MemPointerRecord* cur_p = (MemPointerRecord*)_itr.current();
+ if (cur_p == NULL) {
+ _end_of_array = true;
+ return NULL;
+ }
+
+ MemPointerRecord* next_p;
+ if (cur_p->is_vm_pointer()) {
+ _is_vm_record = true;
+ if (!consolidate_vm_records(&_vm_record)) {
+ return next();
+ }
+ } else { // malloc-ed pointer
+ _is_vm_record = false;
+ next_p = (MemPointerRecord*)_itr.peek_next();
+ if (next_p != NULL && next_p->addr() == cur_p->addr()) {
+ assert(cur_p->is_allocation_record(), "sorting order");
+ assert(!next_p->is_allocation_record(), "sorting order");
+ _itr.next();
+ if (cur_p->seq() < next_p->seq()) {
+ cur_p = next_p;
+ }
+ }
+ if (MemTracker::track_callsite()) {
+ _malloc_record.init((MemPointerRecordEx*)cur_p);
+ } else {
+ _malloc_record.init((MemPointerRecord*)cur_p);
+ }
+
+ _itr.next();
+ }
+ return current();
+}
+
+MemSnapshot::MemSnapshot() {
+ if (MemTracker::track_callsite()) {
+ _alloc_ptrs = new (std::nothrow) MemPointerArrayImpl<MemPointerRecordEx>();
+ _vm_ptrs = new (std::nothrow)MemPointerArrayImpl<VMMemRegionEx>(64, true);
+ _staging_area = new (std::nothrow)MemPointerArrayImpl<SeqMemPointerRecordEx>();
+ } else {
+ _alloc_ptrs = new (std::nothrow) MemPointerArrayImpl<MemPointerRecord>();
+ _vm_ptrs = new (std::nothrow)MemPointerArrayImpl<VMMemRegion>(64, true);
+ _staging_area = new (std::nothrow)MemPointerArrayImpl<SeqMemPointerRecord>();
+ }
+
+ _lock = new (std::nothrow) Mutex(Monitor::native, "memSnapshotLock");
+ NOT_PRODUCT(_untracked_count = 0;)
+}
+
+MemSnapshot::~MemSnapshot() {
+ assert(MemTracker::shutdown_in_progress(), "native memory tracking still on");
+ {
+ MutexLockerEx locker(_lock);
+ if (_staging_area != NULL) {
+ delete _staging_area;
+ _staging_area = NULL;
+ }
+
+ if (_alloc_ptrs != NULL) {
+ delete _alloc_ptrs;
+ _alloc_ptrs = NULL;
+ }
+
+ if (_vm_ptrs != NULL) {
+ delete _vm_ptrs;
+ _vm_ptrs = NULL;
+ }
+ }
+
+ if (_lock != NULL) {
+ delete _lock;
+ _lock = NULL;
+ }
+}
+
+void MemSnapshot::copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src) {
+ assert(dest != NULL && src != NULL, "Just check");
+ assert(dest->addr() == src->addr(), "Just check");
+
+ MEMFLAGS flags = dest->flags();
+
+ if (MemTracker::track_callsite()) {
+ *(MemPointerRecordEx*)dest = *(MemPointerRecordEx*)src;
+ } else {
+ *dest = *src;
+ }
+}
+
+
+// merge a per-thread memory recorder to the staging area
+bool MemSnapshot::merge(MemRecorder* rec) {
+ assert(rec != NULL && !rec->out_of_memory(), "Just check");
+
+ // out of memory
+ if (_staging_area == NULL || _staging_area->out_of_memory()) {
+ return false;
+ }
+
+ SequencedRecordIterator itr(rec->pointer_itr());
+
+ MutexLockerEx lock(_lock, true);
+ MemPointerIterator staging_itr(_staging_area);
+ MemPointerRecord *p1, *p2;
+ p1 = (MemPointerRecord*) itr.current();
+ while (p1 != NULL) {
+ p2 = (MemPointerRecord*)staging_itr.locate(p1->addr());
+ // we have not seen this memory block, so just add to staging area
+ if (p2 == NULL) {
+ if (!staging_itr.insert(p1)) {
+ return false;
+ }
+ } else if (p1->addr() == p2->addr()) {
+ MemPointerRecord* staging_next = (MemPointerRecord*)staging_itr.peek_next();
+ // a memory block can have many tagging records, find right one to replace or
+ // right position to insert
+ while (staging_next != NULL && staging_next->addr() == p1->addr()) {
+ if ((staging_next->flags() & MemPointerRecord::tag_masks) <=
+ (p1->flags() & MemPointerRecord::tag_masks)) {
+ p2 = (MemPointerRecord*)staging_itr.next();
+ staging_next = (MemPointerRecord*)staging_itr.peek_next();
+ } else {
+ break;
+ }
+ }
+ int df = (p1->flags() & MemPointerRecord::tag_masks) -
+ (p2->flags() & MemPointerRecord::tag_masks);
+ if (df == 0) {
+ assert(p1->seq() > 0, "not sequenced");
+ assert(p2->seq() > 0, "not sequenced");
+ if (p1->seq() > p2->seq()) {
+ copy_pointer(p2, p1);
+ }
+ } else if (df < 0) {
+ if (!staging_itr.insert(p1)) {
+ return false;
+ }
+ } else {
+ if (!staging_itr.insert_after(p1)) {
+ return false;
+ }
+ }
+ } else if (p1->addr() < p2->addr()) {
+ if (!staging_itr.insert(p1)) {
+ return false;
+ }
+ } else {
+ if (!staging_itr.insert_after(p1)) {
+ return false;
+ }
+ }
+ p1 = (MemPointerRecord*)itr.next();
+ }
+ NOT_PRODUCT(void check_staging_data();)
+ return true;
+}
+
+
+
+// promote data to next generation
+void MemSnapshot::promote() {
+ assert(_alloc_ptrs != NULL && _staging_area != NULL && _vm_ptrs != NULL,
+ "Just check");
+ MutexLockerEx lock(_lock, true);
+ StagingWalker walker(_staging_area);
+ MemPointerIterator malloc_itr(_alloc_ptrs);
+ VMMemPointerIterator vm_itr(_vm_ptrs);
+ MemPointer* cur = walker.current();
+ while (cur != NULL) {
+ if (walker.is_vm_record()) {
+ VMMemRegion* cur_vm = (VMMemRegion*)cur;
+ VMMemRegion* p = (VMMemRegion*)vm_itr.locate(cur_vm->addr());
+ cur_vm = (VMMemRegion*)cur;
+ if (p != NULL && (p->contains(cur_vm) || p->base() == cur_vm->base())) {
+ assert(p->is_reserve_record() ||
+ p->is_commit_record(), "wrong vm record type");
+ // resize existing reserved range
+ if (cur_vm->is_reserve_record() && p->base() == cur_vm->base()) {
+ assert(cur_vm->size() >= p->committed_size(), "incorrect resizing");
+ p->set_reserved_size(cur_vm->size());
+ } else if (cur_vm->is_commit_record()) {
+ p->commit(cur_vm->committed_size());
+ } else if (cur_vm->is_uncommit_record()) {
+ p->uncommit(cur_vm->committed_size());
+ if (!p->is_reserve_record() && p->committed_size() == 0) {
+ vm_itr.remove();
+ }
+ } else if (cur_vm->is_type_tagging_record()) {
+ p->tag(cur_vm->flags());
+ } else if (cur_vm->is_release_record()) {
+ if (cur_vm->base() == p->base() && cur_vm->size() == p->size()) {
+ // release the whole range
+ vm_itr.remove();
+ } else {
+ // partial release
+ p->partial_release(cur_vm->base(), cur_vm->size());
+ }
+ } else {
+ // we do see multiple reserver on the same vm range
+ assert((cur_vm->is_commit_record() || cur_vm->is_reserve_record()) &&
+ cur_vm->base() == p->base() && cur_vm->size() == p->size(), "bad record");
+ p->tag(cur_vm->flags());
+ }
+ } else {
+ if(cur_vm->is_reserve_record()) {
+ if (p == NULL || p->base() > cur_vm->base()) {
+ vm_itr.insert(cur_vm);
+ } else {
+ vm_itr.insert_after(cur_vm);
+ }
+ } else {
+#ifdef ASSERT
+ // In theory, we should assert without conditions. However, in case of native
+ // thread stack, NMT explicitly releases the thread stack in Thread's destructor,
+ // due to platform dependent behaviors. On some platforms, we see uncommit/release
+ // native thread stack, but some, we don't.
+ if (!cur_vm->is_uncommit_record() && !cur_vm->is_deallocation_record()) {
+ ShouldNotReachHere();
+ }
+#endif
+ }
+ }
+ } else {
+ MemPointerRecord* cur_p = (MemPointerRecord*)cur;
+ MemPointerRecord* p = (MemPointerRecord*)malloc_itr.locate(cur->addr());
+ if (p != NULL && cur_p->addr() == p->addr()) {
+ assert(p->is_allocation_record() || p->is_arena_size_record(), "untracked");
+ if (cur_p->is_allocation_record() || cur_p->is_arena_size_record()) {
+ copy_pointer(p, cur_p);
+ } else { // deallocation record
+ assert(cur_p->is_deallocation_record(), "wrong record type");
+
+ // we are removing an arena record, we also need to remove its 'size'
+ // record behind it
+ if (p->is_arena_record()) {
+ MemPointerRecord* next_p = (MemPointerRecord*)malloc_itr.peek_next();
+ if (next_p->is_arena_size_record()) {
+ assert(next_p->is_size_record_of_arena(p), "arena records dont match");
+ malloc_itr.remove();
+ }
+ }
+ malloc_itr.remove();
+ }
+ } else {
+ if (cur_p->is_arena_size_record()) {
+ MemPointerRecord* prev_p = (MemPointerRecord*)malloc_itr.peek_prev();
+ if (prev_p != NULL &&
+ (!prev_p->is_arena_record() || !cur_p->is_size_record_of_arena(prev_p))) {
+ // arena already deallocated
+ cur_p = NULL;
+ }
+ }
+ if (cur_p != NULL) {
+ if (cur_p->is_allocation_record() || cur_p->is_arena_size_record()) {
+ if (p != NULL && cur_p->addr() > p->addr()) {
+ malloc_itr.insert_after(cur);
+ } else {
+ malloc_itr.insert(cur);
+ }
+ }
+#ifndef PRODUCT
+ else if (!has_allocation_record(cur_p->addr())){
+ // NMT can not track some startup memory, which allocated before NMT
+ // is enabled
+ _untracked_count ++;
+ }
+#endif
+ }
+ }
+ }
+
+ cur = walker.next();
+ }
+ NOT_PRODUCT(check_malloc_pointers();)
+ _staging_area->shrink();
+ _staging_area->clear();
+}
+
+
+#ifdef ASSERT
+void MemSnapshot::print_snapshot_stats(outputStream* st) {
+ st->print_cr("Snapshot:");
+ st->print_cr("\tMalloced: %d/%d [%5.2f%%] %dKB", _alloc_ptrs->length(), _alloc_ptrs->capacity(),
+ (100.0 * (float)_alloc_ptrs->length()) / (float)_alloc_ptrs->capacity(), _alloc_ptrs->instance_size()/K);
+
+ st->print_cr("\tVM: %d/%d [%5.2f%%] %dKB", _vm_ptrs->length(), _vm_ptrs->capacity(),
+ (100.0 * (float)_vm_ptrs->length()) / (float)_vm_ptrs->capacity(), _vm_ptrs->instance_size()/K);
+
+ st->print_cr("\tStaging: %d/%d [%5.2f%%] %dKB", _staging_area->length(), _staging_area->capacity(),
+ (100.0 * (float)_staging_area->length()) / (float)_staging_area->capacity(), _staging_area->instance_size()/K);
+
+ st->print_cr("\tUntracked allocation: %d", _untracked_count);
+}
+
+void MemSnapshot::check_malloc_pointers() {
+ MemPointerArrayIteratorImpl mItr(_alloc_ptrs);
+ MemPointerRecord* p = (MemPointerRecord*)mItr.current();
+ MemPointerRecord* prev = NULL;
+ while (p != NULL) {
+ if (prev != NULL) {
+ assert(p->addr() >= prev->addr(), "sorting order");
+ }
+ prev = p;
+ p = (MemPointerRecord*)mItr.next();
+ }
+}
+
+void MemSnapshot::check_staging_data() {
+ MemPointerArrayIteratorImpl itr(_staging_area);
+ MemPointerRecord* cur = (MemPointerRecord*)itr.current();
+ MemPointerRecord* next = (MemPointerRecord*)itr.next();
+ while (next != NULL) {
+ assert((next->addr() > cur->addr()) ||
+ ((next->flags() & MemPointerRecord::tag_masks) >
+ (cur->flags() & MemPointerRecord::tag_masks)),
+ "sorting order");
+ cur = next;
+ next = (MemPointerRecord*)itr.next();
+ }
+}
+
+bool MemSnapshot::has_allocation_record(address addr) {
+ MemPointerArrayIteratorImpl itr(_staging_area);
+ MemPointerRecord* cur = (MemPointerRecord*)itr.current();
+ while (cur != NULL) {
+ if (cur->addr() == addr && cur->is_allocation_record()) {
+ return true;
+ }
+ cur = (MemPointerRecord*)itr.next();
+ }
+ return false;
+}
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memSnapshot.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,286 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_MEM_SNAPSHOT_HPP
+#define SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "services/memBaseline.hpp"
+#include "services/memPtrArray.hpp"
+
+
+// Snapshot pointer array iterator
+
+// The pointer array contains malloc-ed pointers
+class MemPointerIterator : public MemPointerArrayIteratorImpl {
+ public:
+ MemPointerIterator(MemPointerArray* arr):
+ MemPointerArrayIteratorImpl(arr) {
+ assert(arr != NULL, "null array");
+ }
+
+#ifdef ASSERT
+ virtual bool is_dup_pointer(const MemPointer* ptr1,
+ const MemPointer* ptr2) const {
+ MemPointerRecord* p1 = (MemPointerRecord*)ptr1;
+ MemPointerRecord* p2 = (MemPointerRecord*)ptr2;
+
+ if (p1->addr() != p2->addr()) return false;
+ if ((p1->flags() & MemPointerRecord::tag_masks) !=
+ (p2->flags() & MemPointerRecord::tag_masks)) {
+ return false;
+ }
+ // we do see multiple commit/uncommit on the same memory, it is ok
+ return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
+ (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
+ }
+
+ virtual bool insert(MemPointer* ptr) {
+ if (_pos > 0) {
+ MemPointer* p1 = (MemPointer*)ptr;
+ MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
+ assert(!is_dup_pointer(p1, p2),
+ "dup pointer");
+ }
+ if (_pos < _array->length() -1) {
+ MemPointer* p1 = (MemPointer*)ptr;
+ MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
+ assert(!is_dup_pointer(p1, p2),
+ "dup pointer");
+ }
+ return _array->insert_at(ptr, _pos);
+ }
+
+ virtual bool insert_after(MemPointer* ptr) {
+ if (_pos > 0) {
+ MemPointer* p1 = (MemPointer*)ptr;
+ MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
+ assert(!is_dup_pointer(p1, p2),
+ "dup pointer");
+ }
+ if (_pos < _array->length() - 1) {
+ MemPointer* p1 = (MemPointer*)ptr;
+ MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
+
+ assert(!is_dup_pointer(p1, p2),
+ "dup pointer");
+ }
+ if (_array->insert_at(ptr, _pos + 1)) {
+ _pos ++;
+ return true;
+ }
+ return false;
+ }
+#endif
+
+ virtual MemPointer* locate(address addr) {
+ MemPointer* cur = current();
+ while (cur != NULL && cur->addr() < addr) {
+ cur = next();
+ }
+ return cur;
+ }
+};
+
+class VMMemPointerIterator : public MemPointerIterator {
+ public:
+ VMMemPointerIterator(MemPointerArray* arr):
+ MemPointerIterator(arr) {
+ }
+
+ // locate an exiting record that contains specified address, or
+ // the record, where the record with specified address, should
+ // be inserted
+ virtual MemPointer* locate(address addr) {
+ VMMemRegion* cur = (VMMemRegion*)current();
+ VMMemRegion* next_p;
+
+ while (cur != NULL) {
+ if (cur->base() > addr) {
+ return cur;
+ } else {
+ // find nearest existing range that has base address <= addr
+ next_p = (VMMemRegion*)peek_next();
+ if (next_p != NULL && next_p->base() <= addr) {
+ cur = (VMMemRegion*)next();
+ continue;
+ }
+ }
+
+ if (cur->is_reserve_record() &&
+ cur->base() <= addr &&
+ (cur->base() + cur->size() > addr)) {
+ return cur;
+ } else if (cur->is_commit_record() &&
+ cur->base() <= addr &&
+ (cur->base() + cur->committed_size() > addr)) {
+ return cur;
+ }
+ cur = (VMMemRegion*)next();
+ }
+ return NULL;
+ }
+
+#ifdef ASSERT
+ virtual bool is_dup_pointer(const MemPointer* ptr1,
+ const MemPointer* ptr2) const {
+ VMMemRegion* p1 = (VMMemRegion*)ptr1;
+ VMMemRegion* p2 = (VMMemRegion*)ptr2;
+
+ if (p1->addr() != p2->addr()) return false;
+ if ((p1->flags() & MemPointerRecord::tag_masks) !=
+ (p2->flags() & MemPointerRecord::tag_masks)) {
+ return false;
+ }
+ // we do see multiple commit/uncommit on the same memory, it is ok
+ return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
+ (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
+ }
+#endif
+};
+
+class StagingWalker : public MemPointerArrayIterator {
+ private:
+ MemPointerArrayIteratorImpl _itr;
+ bool _is_vm_record;
+ bool _end_of_array;
+ VMMemRegionEx _vm_record;
+ MemPointerRecordEx _malloc_record;
+
+ public:
+ StagingWalker(MemPointerArray* arr): _itr(arr) {
+ _end_of_array = false;
+ next();
+ }
+
+ // return the pointer at current position
+ MemPointer* current() const {
+ if (_end_of_array) {
+ return NULL;
+ }
+ if (is_vm_record()) {
+ return (MemPointer*)&_vm_record;
+ } else {
+ return (MemPointer*)&_malloc_record;
+ }
+ }
+
+ // return the next pointer and advance current position
+ MemPointer* next();
+
+ // type of 'current' record
+ bool is_vm_record() const {
+ return _is_vm_record;
+ }
+
+ // return the next poinger without advancing current position
+ MemPointer* peek_next() const {
+ assert(false, "not supported");
+ return NULL;
+ }
+
+ MemPointer* peek_prev() const {
+ assert(false, "not supported");
+ return NULL;
+ }
+ // remove the pointer at current position
+ void remove() {
+ assert(false, "not supported");
+ }
+
+ // insert the pointer at current position
+ bool insert(MemPointer* ptr) {
+ assert(false, "not supported");
+ return false;
+ }
+
+ bool insert_after(MemPointer* ptr) {
+ assert(false, "not supported");
+ return false;
+ }
+
+ private:
+ // consolidate all records referring to this vm region
+ bool consolidate_vm_records(VMMemRegionEx* vm_rec);
+};
+
+class MemBaseline;
+
+class MemSnapshot : public CHeapObj<mtNMT> {
+ private:
+ // the following two arrays contain records of all known lived memory blocks
+ // live malloc-ed memory pointers
+ MemPointerArray* _alloc_ptrs;
+ // live virtual memory pointers
+ MemPointerArray* _vm_ptrs;
+
+ // stagging a generation's data, before
+ // it can be prompted to snapshot
+ MemPointerArray* _staging_area;
+
+ // the lock to protect this snapshot
+ Monitor* _lock;
+
+ NOT_PRODUCT(size_t _untracked_count;)
+ friend class MemBaseline;
+
+ public:
+ MemSnapshot();
+ virtual ~MemSnapshot();
+
+ // if we are running out of native memory
+ bool out_of_memory() const {
+ return (_alloc_ptrs == NULL || _staging_area == NULL ||
+ _vm_ptrs == NULL || _lock == NULL ||
+ _alloc_ptrs->out_of_memory() ||
+ _staging_area->out_of_memory() ||
+ _vm_ptrs->out_of_memory());
+ }
+
+ // merge a per-thread memory recorder into staging area
+ bool merge(MemRecorder* rec);
+ // promote staged data to snapshot
+ void promote();
+
+
+ void wait(long timeout) {
+ assert(_lock != NULL, "Just check");
+ MonitorLockerEx locker(_lock);
+ locker.wait(true, timeout);
+ }
+
+ NOT_PRODUCT(void print_snapshot_stats(outputStream* st);)
+ NOT_PRODUCT(void check_staging_data();)
+ NOT_PRODUCT(void check_malloc_pointers();)
+ NOT_PRODUCT(bool has_allocation_record(address addr);)
+
+ private:
+ // copy pointer data from src to dest
+ void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src);
+};
+
+
+#endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memTrackWorker.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "runtime/threadCritical.hpp"
+#include "services/memTracker.hpp"
+#include "services/memTrackWorker.hpp"
+#include "utilities/decoder.hpp"
+#include "utilities/vmError.hpp"
+
+MemTrackWorker::MemTrackWorker() {
+ // create thread uses cgc thread type for now. We should revisit
+ // the option, or create new thread type.
+ _has_error = !os::create_thread(this, os::cgc_thread);
+ set_name("MemTrackWorker", 0);
+
+ // initial generation circuit buffer
+ if (!has_error()) {
+ _head = _tail = 0;
+ for(int index = 0; index < MAX_GENERATIONS; index ++) {
+ _gen[index] = NULL;
+ }
+ }
+ NOT_PRODUCT(_sync_point_count = 0;)
+ NOT_PRODUCT(_merge_count = 0;)
+ NOT_PRODUCT(_last_gen_in_use = 0;)
+}
+
+MemTrackWorker::~MemTrackWorker() {
+ for (int index = 0; index < MAX_GENERATIONS; index ++) {
+ MemRecorder* rc = _gen[index];
+ if (rc != NULL) {
+ delete rc;
+ }
+ }
+}
+
+void* MemTrackWorker::operator new(size_t size) {
+ assert(false, "use nothrow version");
+ return NULL;
+}
+
+void* MemTrackWorker::operator new(size_t size, const std::nothrow_t& nothrow_constant) {
+ return allocate(size, false, mtNMT);
+}
+
+void MemTrackWorker::start() {
+ os::start_thread(this);
+}
+
+/*
+ * Native memory tracking worker thread loop:
+ * 1. merge one generation of memory recorders to staging area
+ * 2. promote staging data to memory snapshot
+ *
+ * This thread can run through safepoint.
+ */
+
+void MemTrackWorker::run() {
+ assert(MemTracker::is_on(), "native memory tracking is off");
+ this->initialize_thread_local_storage();
+ this->record_stack_base_and_size();
+ MemSnapshot* snapshot = MemTracker::get_snapshot();
+ assert(snapshot != NULL, "Worker should not be started");
+ MemRecorder* rec;
+
+ while (!MemTracker::shutdown_in_progress()) {
+ NOT_PRODUCT(_last_gen_in_use = generations_in_use();)
+ {
+ // take a recorder from earliest generation in buffer
+ ThreadCritical tc;
+ rec = _gen[_head];
+ if (rec != NULL) {
+ _gen[_head] = rec->next();
+ }
+ assert(count_recorder(_gen[_head]) <= MemRecorder::_instance_count,
+ "infinite loop after dequeue");
+ }
+ if (rec != NULL) {
+ // merge the recorder into staging area
+ bool result = snapshot->merge(rec);
+ assert(result, "merge failed");
+ debug_only(_merge_count ++;)
+ MemTracker::release_thread_recorder(rec);
+ } else {
+ // no more recorder to merge, promote staging area
+ // to snapshot
+ if (_head != _tail) {
+ {
+ ThreadCritical tc;
+ if (_gen[_head] != NULL || _head == _tail) {
+ continue;
+ }
+ // done with this generation, increment _head pointer
+ _head = (_head + 1) % MAX_GENERATIONS;
+ }
+ // promote this generation data to snapshot
+ snapshot->promote();
+ } else {
+ snapshot->wait(1000);
+ ThreadCritical tc;
+ // check if more data arrived
+ if (_gen[_head] == NULL) {
+ _gen[_head] = MemTracker::get_pending_recorders();
+ }
+ }
+ }
+ }
+ assert(MemTracker::shutdown_in_progress(), "just check");
+
+ // transites to final shutdown
+ MemTracker::final_shutdown();
+}
+
+// at synchronization point, where 'safepoint visible' Java threads are blocked
+// at a safepoint, and the rest of threads are blocked on ThreadCritical lock.
+// The caller MemTracker::sync() already takes ThreadCritical before calling this
+// method.
+//
+// Following tasks are performed:
+// 1. add all recorders in pending queue to current generation
+// 2. increase generation
+
+void MemTrackWorker::at_sync_point(MemRecorder* rec) {
+ NOT_PRODUCT(_sync_point_count ++;)
+ assert(count_recorder(rec) <= MemRecorder::_instance_count,
+ "pending queue has infinite loop");
+
+ bool out_of_generation_buffer = false;
+ // check shutdown state inside ThreadCritical
+ if (MemTracker::shutdown_in_progress()) return;
+ // append the recorders to the end of the generation
+ if( rec != NULL) {
+ MemRecorder* cur_head = _gen[_tail];
+ if (cur_head == NULL) {
+ _gen[_tail] = rec;
+ } else {
+ while (cur_head->next() != NULL) {
+ cur_head = cur_head->next();
+ }
+ cur_head->set_next(rec);
+ }
+ }
+ assert(count_recorder(rec) <= MemRecorder::_instance_count,
+ "after add to current generation has infinite loop");
+ // we have collected all recorders for this generation. If there is data,
+ // we need to increment _tail to start a new generation.
+ if (_gen[_tail] != NULL || _head == _tail) {
+ _tail = (_tail + 1) % MAX_GENERATIONS;
+ out_of_generation_buffer = (_tail == _head);
+ }
+
+ if (out_of_generation_buffer) {
+ MemTracker::shutdown(MemTracker::NMT_out_of_generation);
+ }
+}
+
+#ifndef PRODUCT
+int MemTrackWorker::count_recorder(const MemRecorder* head) {
+ int count = 0;
+ while(head != NULL) {
+ count ++;
+ head = head->next();
+ }
+ return count;
+}
+
+int MemTrackWorker::count_pending_recorders() const {
+ int count = 0;
+ for (int index = 0; index < MAX_GENERATIONS; index ++) {
+ MemRecorder* head = _gen[index];
+ if (head != NULL) {
+ count += count_recorder(head);
+ }
+ }
+ return count;
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memTrackWorker.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_MEM_TRACK_WORKER_HPP
+#define SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/thread.hpp"
+#include "services/memRecorder.hpp"
+
+// Maximum MAX_GENERATIONS generation data can be tracked.
+#define MAX_GENERATIONS 512
+
+
+class MemTrackWorker : public NamedThread {
+ private:
+ // circular buffer. This buffer contains recorders to be merged into global
+ // snaphsot.
+ // Each slot holds a linked list of memory recorders, that contains one
+ // generation of memory data.
+ MemRecorder* _gen[MAX_GENERATIONS];
+ int _head, _tail; // head and tail pointers to above circular buffer
+
+ bool _has_error;
+
+ public:
+ MemTrackWorker();
+ ~MemTrackWorker();
+ _NOINLINE_ void* operator new(size_t size);
+ _NOINLINE_ void* operator new(size_t size, const std::nothrow_t& nothrow_constant);
+
+ void start();
+ void run();
+
+ inline bool has_error() const { return _has_error; }
+
+ // task at synchronization point
+ void at_sync_point(MemRecorder* pending_recorders);
+
+ // for debugging purpose, they are not thread safe.
+ NOT_PRODUCT(static int count_recorder(const MemRecorder* head);)
+ NOT_PRODUCT(int count_pending_recorders() const;)
+
+ NOT_PRODUCT(int _sync_point_count;)
+ NOT_PRODUCT(int _merge_count;)
+ NOT_PRODUCT(int _last_gen_in_use;)
+
+ inline int generations_in_use() const {
+ return (_tail <= _head ? (_head - _tail + 1) : (MAX_GENERATIONS - (_tail - _head) + 1));
+ }
+};
+
+#endif // SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memTracker.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "runtime/atomic.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/safepoint.hpp"
+#include "runtime/threadCritical.hpp"
+#include "services/memPtr.hpp"
+#include "services/memReporter.hpp"
+#include "services/memTracker.hpp"
+#include "utilities/decoder.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+bool NMT_track_callsite = false;
+
+// walk all 'known' threads at NMT sync point, and collect their recorders
+void SyncThreadRecorderClosure::do_thread(Thread* thread) {
+ assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
+ if (thread->is_Java_thread()) {
+ JavaThread* javaThread = (JavaThread*)thread;
+ MemRecorder* recorder = javaThread->get_recorder();
+ if (recorder != NULL) {
+ MemTracker::enqueue_pending_recorder(recorder);
+ javaThread->set_recorder(NULL);
+ }
+ }
+ _thread_count ++;
+}
+
+
+MemRecorder* MemTracker::_global_recorder = NULL;
+MemSnapshot* MemTracker::_snapshot = NULL;
+MemBaseline MemTracker::_baseline;
+Mutex MemTracker::_query_lock(Monitor::native, "NMT_queryLock");
+volatile MemRecorder* MemTracker::_merge_pending_queue = NULL;
+volatile MemRecorder* MemTracker::_pooled_recorders = NULL;
+MemTrackWorker* MemTracker::_worker_thread = NULL;
+int MemTracker::_sync_point_skip_count = 0;
+MemTracker::NMTLevel MemTracker::_tracking_level = MemTracker::NMT_off;
+volatile MemTracker::NMTStates MemTracker::_state = NMT_uninited;
+MemTracker::ShutdownReason MemTracker::_reason = NMT_shutdown_none;
+int MemTracker::_thread_count = 255;
+volatile jint MemTracker::_pooled_recorder_count = 0;
+debug_only(intx MemTracker::_main_thread_tid = 0;)
+debug_only(volatile jint MemTracker::_pending_recorder_count = 0;)
+
+void MemTracker::init_tracking_options(const char* option_line) {
+ _tracking_level = NMT_off;
+ if (strncmp(option_line, "=summary", 8) == 0) {
+ _tracking_level = NMT_summary;
+ } else if (strncmp(option_line, "=detail", 8) == 0) {
+ _tracking_level = NMT_detail;
+ }
+}
+
+// first phase of bootstrapping, when VM is still in single-threaded mode.
+void MemTracker::bootstrap_single_thread() {
+ if (_tracking_level > NMT_off) {
+ assert(_state == NMT_uninited, "wrong state");
+
+ // NMT is not supported with UseMallocOnly is on. NMT can NOT
+ // handle the amount of malloc data without significantly impacting
+ // runtime performance when this flag is on.
+ if (UseMallocOnly) {
+ shutdown(NMT_use_malloc_only);
+ return;
+ }
+
+ debug_only(_main_thread_tid = os::current_thread_id();)
+ _state = NMT_bootstrapping_single_thread;
+ NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
+ }
+}
+
+// second phase of bootstrapping, when VM is about to or already entered multi-theaded mode.
+void MemTracker::bootstrap_multi_thread() {
+ if (_tracking_level > NMT_off && _state == NMT_bootstrapping_single_thread) {
+ // create nmt lock for multi-thread execution
+ assert(_main_thread_tid == os::current_thread_id(), "wrong thread");
+ _state = NMT_bootstrapping_multi_thread;
+ NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
+ }
+}
+
+// fully start nmt
+void MemTracker::start() {
+ // Native memory tracking is off from command line option
+ if (_tracking_level == NMT_off || shutdown_in_progress()) return;
+
+ assert(_main_thread_tid == os::current_thread_id(), "wrong thread");
+ assert(_state == NMT_bootstrapping_multi_thread, "wrong state");
+
+ _snapshot = new (std::nothrow)MemSnapshot();
+ if (_snapshot != NULL && !_snapshot->out_of_memory()) {
+ if (start_worker()) {
+ _state = NMT_started;
+ NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
+ return;
+ }
+ }
+
+ // fail to start native memory tracking, shut it down
+ shutdown(NMT_initialization);
+}
+
+/**
+ * Shutting down native memory tracking.
+ * We can not shutdown native memory tracking immediately, so we just
+ * setup shutdown pending flag, every native memory tracking component
+ * should orderly shut itself down.
+ *
+ * The shutdown sequences:
+ * 1. MemTracker::shutdown() sets MemTracker to shutdown pending state
+ * 2. Worker thread calls MemTracker::final_shutdown(), which transites
+ * MemTracker to final shutdown state.
+ * 3. At sync point, MemTracker does final cleanup, before sets memory
+ * tracking level to off to complete shutdown.
+ */
+void MemTracker::shutdown(ShutdownReason reason) {
+ if (_tracking_level == NMT_off) return;
+
+ if (_state <= NMT_bootstrapping_single_thread) {
+ // we still in single thread mode, there is not contention
+ _state = NMT_shutdown_pending;
+ _reason = reason;
+ } else {
+ // we want to know who initialized shutdown
+ if ((jint)NMT_started == Atomic::cmpxchg((jint)NMT_shutdown_pending,
+ (jint*)&_state, (jint)NMT_started)) {
+ _reason = reason;
+ }
+ }
+}
+
+// final phase of shutdown
+void MemTracker::final_shutdown() {
+ // delete all pending recorders and pooled recorders
+ delete_all_pending_recorders();
+ delete_all_pooled_recorders();
+
+ {
+ // shared baseline and snapshot are the only objects needed to
+ // create query results
+ MutexLockerEx locker(&_query_lock, true);
+ // cleanup baseline data and snapshot
+ _baseline.clear();
+ delete _snapshot;
+ _snapshot = NULL;
+ }
+
+ // shutdown shared decoder instance, since it is only
+ // used by native memory tracking so far.
+ Decoder::shutdown();
+
+ MemTrackWorker* worker = NULL;
+ {
+ ThreadCritical tc;
+ // can not delete worker inside the thread critical
+ if (_worker_thread != NULL && Thread::current() == _worker_thread) {
+ worker = _worker_thread;
+ _worker_thread = NULL;
+ }
+ }
+ if (worker != NULL) {
+ delete worker;
+ }
+ _state = NMT_final_shutdown;
+}
+
+// delete all pooled recorders
+void MemTracker::delete_all_pooled_recorders() {
+ // free all pooled recorders
+ volatile MemRecorder* cur_head = _pooled_recorders;
+ if (cur_head != NULL) {
+ MemRecorder* null_ptr = NULL;
+ while (cur_head != NULL && (void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr,
+ (void*)&_pooled_recorders, (void*)cur_head)) {
+ cur_head = _pooled_recorders;
+ }
+ if (cur_head != NULL) {
+ delete cur_head;
+ _pooled_recorder_count = 0;
+ }
+ }
+}
+
+// delete all recorders in pending queue
+void MemTracker::delete_all_pending_recorders() {
+ // free all pending recorders
+ MemRecorder* pending_head = get_pending_recorders();
+ if (pending_head != NULL) {
+ delete pending_head;
+ }
+}
+
+/*
+ * retrieve per-thread recorder of specified thread.
+ * if thread == NULL, it means global recorder
+ */
+MemRecorder* MemTracker::get_thread_recorder(JavaThread* thread) {
+ if (shutdown_in_progress()) return NULL;
+
+ MemRecorder* rc;
+ if (thread == NULL) {
+ rc = _global_recorder;
+ } else {
+ rc = thread->get_recorder();
+ }
+
+ if (rc != NULL && rc->is_full()) {
+ enqueue_pending_recorder(rc);
+ rc = NULL;
+ }
+
+ if (rc == NULL) {
+ rc = get_new_or_pooled_instance();
+ if (thread == NULL) {
+ _global_recorder = rc;
+ } else {
+ thread->set_recorder(rc);
+ }
+ }
+ return rc;
+}
+
+/*
+ * get a per-thread recorder from pool, or create a new one if
+ * there is not one available.
+ */
+MemRecorder* MemTracker::get_new_or_pooled_instance() {
+ MemRecorder* cur_head = const_cast<MemRecorder*> (_pooled_recorders);
+ if (cur_head == NULL) {
+ MemRecorder* rec = new (std::nothrow)MemRecorder();
+ if (rec == NULL || rec->out_of_memory()) {
+ shutdown(NMT_out_of_memory);
+ if (rec != NULL) {
+ delete rec;
+ rec = NULL;
+ }
+ }
+ return rec;
+ } else {
+ MemRecorder* next_head = cur_head->next();
+ if ((void*)cur_head != Atomic::cmpxchg_ptr((void*)next_head, (void*)&_pooled_recorders,
+ (void*)cur_head)) {
+ return get_new_or_pooled_instance();
+ }
+ cur_head->set_next(NULL);
+ Atomic::dec(&_pooled_recorder_count);
+ debug_only(cur_head->set_generation();)
+ return cur_head;
+ }
+}
+
+/*
+ * retrieve all recorders in pending queue, and empty the queue
+ */
+MemRecorder* MemTracker::get_pending_recorders() {
+ MemRecorder* cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
+ MemRecorder* null_ptr = NULL;
+ while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr, (void*)&_merge_pending_queue,
+ (void*)cur_head)) {
+ cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
+ }
+ debug_only(Atomic::store(0, &_pending_recorder_count));
+ return cur_head;
+}
+
+/*
+ * release a recorder to recorder pool.
+ */
+void MemTracker::release_thread_recorder(MemRecorder* rec) {
+ assert(rec != NULL, "null recorder");
+ // we don't want to pool too many recorders
+ rec->set_next(NULL);
+ if (shutdown_in_progress() || _pooled_recorder_count > _thread_count * 2) {
+ delete rec;
+ return;
+ }
+
+ rec->clear();
+ MemRecorder* cur_head = const_cast<MemRecorder*>(_pooled_recorders);
+ rec->set_next(cur_head);
+ while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_pooled_recorders,
+ (void*)cur_head)) {
+ cur_head = const_cast<MemRecorder*>(_pooled_recorders);
+ rec->set_next(cur_head);
+ }
+ Atomic::inc(&_pooled_recorder_count);
+}
+
+/*
+ * This is the most important method in whole nmt implementation.
+ *
+ * Create a memory record.
+ * 1. When nmt is in single-threaded bootstrapping mode, no lock is needed as VM
+ * still in single thread mode.
+ * 2. For all threads other than JavaThread, ThreadCritical is needed
+ * to write to recorders to global recorder.
+ * 3. For JavaThreads that are not longer visible by safepoint, also
+ * need to take ThreadCritical and records are written to global
+ * recorders, since these threads are NOT walked by Threads.do_thread().
+ * 4. JavaThreads that are running in native state, have to transition
+ * to VM state before writing to per-thread recorders.
+ * 5. JavaThreads that are running in VM state do not need any lock and
+ * records are written to per-thread recorders.
+ * 6. For a thread has yet to attach VM 'Thread', they need to take
+ * ThreadCritical to write to global recorder.
+ *
+ * Important note:
+ * NO LOCK should be taken inside ThreadCritical lock !!!
+ */
+void MemTracker::create_memory_record(address addr, MEMFLAGS flags,
+ size_t size, address pc, Thread* thread) {
+ if (!shutdown_in_progress()) {
+ // single thread, we just write records direct to global recorder,'
+ // with any lock
+ if (_state == NMT_bootstrapping_single_thread) {
+ assert(_main_thread_tid == os::current_thread_id(), "wrong thread");
+ thread = NULL;
+ } else {
+ if (thread == NULL) {
+ // don't use Thread::current(), since it is possible that
+ // the calling thread has yet to attach to VM 'Thread',
+ // which will result assertion failure
+ thread = ThreadLocalStorage::thread();
+ }
+ }
+
+ if (thread != NULL) {
+#ifdef ASSERT
+ // cause assertion on stack base. This ensures that threads call
+ // Thread::record_stack_base_and_size() method, which will create
+ // thread native stack records.
+ thread->stack_base();
+#endif
+ // for a JavaThread, if it is running in native state, we need to transition it to
+ // VM state, so it can stop at safepoint. JavaThread running in VM state does not
+ // need lock to write records.
+ if (thread->is_Java_thread() && ((JavaThread*)thread)->is_safepoint_visible()) {
+ if (((JavaThread*)thread)->thread_state() == _thread_in_native) {
+ ThreadInVMfromNative trans((JavaThread*)thread);
+ create_record_in_recorder(addr, flags, size, pc, thread);
+ } else {
+ create_record_in_recorder(addr, flags, size, pc, thread);
+ }
+ } else {
+ // other threads, such as worker and watcher threads, etc. need to
+ // take ThreadCritical to write to global recorder
+ ThreadCritical tc;
+ create_record_in_recorder(addr, flags, size, pc, NULL);
+ }
+ } else {
+ if (_state == NMT_bootstrapping_single_thread) {
+ // single thread, no lock needed
+ create_record_in_recorder(addr, flags, size, pc, NULL);
+ } else {
+ // for thread has yet to attach VM 'Thread', we can not use VM mutex.
+ // use native thread critical instead
+ ThreadCritical tc;
+ create_record_in_recorder(addr, flags, size, pc, NULL);
+ }
+ }
+ }
+}
+
+// write a record to proper recorder. No lock can be taken from this method
+// down.
+void MemTracker::create_record_in_recorder(address addr, MEMFLAGS flags,
+ size_t size, address pc, Thread* thread) {
+ assert(thread == NULL || thread->is_Java_thread(), "wrong thread");
+
+ MemRecorder* rc = get_thread_recorder((JavaThread*)thread);
+ if (rc != NULL) {
+ rc->record(addr, flags, size, pc);
+ }
+}
+
+/**
+ * enqueue a recorder to pending queue
+ */
+void MemTracker::enqueue_pending_recorder(MemRecorder* rec) {
+ assert(rec != NULL, "null recorder");
+
+ // we are shutting down, so just delete it
+ if (shutdown_in_progress()) {
+ rec->set_next(NULL);
+ delete rec;
+ return;
+ }
+
+ MemRecorder* cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
+ rec->set_next(cur_head);
+ while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_merge_pending_queue,
+ (void*)cur_head)) {
+ cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
+ rec->set_next(cur_head);
+ }
+ debug_only(Atomic::inc(&_pending_recorder_count);)
+}
+
+/*
+ * The method is called at global safepoint
+ * during it synchronization process.
+ * 1. enqueue all JavaThreads' per-thread recorders
+ * 2. enqueue global recorder
+ * 3. retrieve all pending recorders
+ * 4. reset global sequence number generator
+ * 5. call worker's sync
+ */
+#define MAX_SAFEPOINTS_TO_SKIP 128
+#define SAFE_SEQUENCE_THRESHOLD 30
+#define HIGH_GENERATION_THRESHOLD 60
+
+void MemTracker::sync() {
+ assert(_tracking_level > NMT_off, "NMT is not enabled");
+ assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
+
+ // Some GC tests hit large number of safepoints in short period of time
+ // without meaningful activities. We should prevent going to
+ // sync point in these cases, which can potentially exhaust generation buffer.
+ // Here is the factots to determine if we should go into sync point:
+ // 1. not to overflow sequence number
+ // 2. if we are in danger to overflow generation buffer
+ // 3. how many safepoints we already skipped sync point
+ if (_state == NMT_started) {
+ // worker thread is not ready, no one can manage generation
+ // buffer, so skip this safepoint
+ if (_worker_thread == NULL) return;
+
+ if (_sync_point_skip_count < MAX_SAFEPOINTS_TO_SKIP) {
+ int per_seq_in_use = SequenceGenerator::peek() * 100 / max_jint;
+ int per_gen_in_use = _worker_thread->generations_in_use() * 100 / MAX_GENERATIONS;
+ if (per_seq_in_use < SAFE_SEQUENCE_THRESHOLD && per_gen_in_use >= HIGH_GENERATION_THRESHOLD) {
+ _sync_point_skip_count ++;
+ return;
+ }
+ }
+ _sync_point_skip_count = 0;
+ // walk all JavaThreads to collect recorders
+ SyncThreadRecorderClosure stc;
+ Threads::threads_do(&stc);
+
+ _thread_count = stc.get_thread_count();
+ MemRecorder* pending_recorders = get_pending_recorders();
+
+ {
+ // This method is running at safepoint, with ThreadCritical lock,
+ // it should guarantee that NMT is fully sync-ed.
+ ThreadCritical tc;
+ if (_global_recorder != NULL) {
+ _global_recorder->set_next(pending_recorders);
+ pending_recorders = _global_recorder;
+ _global_recorder = NULL;
+ }
+ SequenceGenerator::reset();
+ // check _worker_thread with lock to avoid racing condition
+ if (_worker_thread != NULL) {
+ _worker_thread->at_sync_point(pending_recorders);
+ }
+ }
+ }
+
+ // now, it is the time to shut whole things off
+ if (_state == NMT_final_shutdown) {
+ _tracking_level = NMT_off;
+
+ // walk all JavaThreads to delete all recorders
+ SyncThreadRecorderClosure stc;
+ Threads::threads_do(&stc);
+ // delete global recorder
+ {
+ ThreadCritical tc;
+ if (_global_recorder != NULL) {
+ delete _global_recorder;
+ _global_recorder = NULL;
+ }
+ }
+
+ _state = NMT_shutdown;
+ }
+}
+
+/*
+ * Start worker thread.
+ */
+bool MemTracker::start_worker() {
+ assert(_worker_thread == NULL, "Just Check");
+ _worker_thread = new (std::nothrow) MemTrackWorker();
+ if (_worker_thread == NULL || _worker_thread->has_error()) {
+ shutdown(NMT_initialization);
+ return false;
+ }
+ _worker_thread->start();
+ return true;
+}
+
+/*
+ * We need to collect a JavaThread's per-thread recorder
+ * before it exits.
+ */
+void MemTracker::thread_exiting(JavaThread* thread) {
+ if (is_on()) {
+ MemRecorder* rec = thread->get_recorder();
+ if (rec != NULL) {
+ enqueue_pending_recorder(rec);
+ thread->set_recorder(NULL);
+ }
+ }
+}
+
+// baseline current memory snapshot
+bool MemTracker::baseline() {
+ MutexLockerEx lock(&_query_lock, true);
+ MemSnapshot* snapshot = get_snapshot();
+ if (snapshot != NULL) {
+ return _baseline.baseline(*snapshot, false);
+ }
+ return false;
+}
+
+// print memory usage from current snapshot
+bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
+ MemBaseline baseline;
+ MutexLockerEx lock(&_query_lock, true);
+ MemSnapshot* snapshot = get_snapshot();
+ if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) {
+ BaselineReporter reporter(out, unit);
+ reporter.report_baseline(baseline, summary_only);
+ return true;
+ }
+ return false;
+}
+
+// compare memory usage between current snapshot and baseline
+bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
+ MutexLockerEx lock(&_query_lock, true);
+ if (_baseline.baselined()) {
+ MemBaseline baseline;
+ MemSnapshot* snapshot = get_snapshot();
+ if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) {
+ BaselineReporter reporter(out, unit);
+ reporter.diff_baselines(baseline, _baseline, summary_only);
+ return true;
+ }
+ }
+ return false;
+}
+
+#ifndef PRODUCT
+void MemTracker::walk_stack(int toSkip, char* buf, int len) {
+ int cur_len = 0;
+ char tmp[1024];
+ address pc;
+
+ while (cur_len < len) {
+ pc = os::get_caller_pc(toSkip + 1);
+ if (pc != NULL && os::dll_address_to_function_name(pc, tmp, sizeof(tmp), NULL)) {
+ jio_snprintf(&buf[cur_len], (len - cur_len), "%s\n", tmp);
+ cur_len = (int)strlen(buf);
+ } else {
+ buf[cur_len] = '\0';
+ break;
+ }
+ toSkip ++;
+ }
+}
+
+void MemTracker::print_tracker_stats(outputStream* st) {
+ st->print_cr("\nMemory Tracker Stats:");
+ st->print_cr("\tMax sequence number = %d", SequenceGenerator::max_seq_num());
+ st->print_cr("\tthead count = %d", _thread_count);
+ st->print_cr("\tArena instance = %d", Arena::_instance_count);
+ st->print_cr("\tpooled recorder count = %d", _pooled_recorder_count);
+ st->print_cr("\tqueued recorder count = %d", _pending_recorder_count);
+ st->print_cr("\tmemory recorder instance count = %d", MemRecorder::_instance_count);
+ if (_worker_thread != NULL) {
+ st->print_cr("\tWorker thread:");
+ st->print_cr("\t\tSync point count = %d", _worker_thread->_sync_point_count);
+ st->print_cr("\t\tpending recorder count = %d", _worker_thread->count_pending_recorders());
+ st->print_cr("\t\tmerge count = %d", _worker_thread->_merge_count);
+ } else {
+ st->print_cr("\tWorker thread is not started");
+ }
+ st->print_cr(" ");
+
+ if (_snapshot != NULL) {
+ _snapshot->print_snapshot_stats(st);
+ } else {
+ st->print_cr("No snapshot");
+ }
+}
+#endif
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/memTracker.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,384 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_MEM_TRACKER_HPP
+#define SHARE_VM_SERVICES_MEM_TRACKER_HPP
+
+#include "memory/allocation.hpp"
+#include "runtime/globals.hpp"
+#include "runtime/mutex.hpp"
+#include "runtime/os.hpp"
+#include "runtime/thread.hpp"
+#include "services/memPtr.hpp"
+#include "services/memRecorder.hpp"
+#include "services/memSnapshot.hpp"
+#include "services/memTrackWorker.hpp"
+
+#ifdef SOLARIS
+#include "thread_solaris.inline.hpp"
+#endif
+
+#ifdef _DEBUG_
+ #define DEBUG_CALLER_PC os::get_caller_pc(3)
+#else
+ #define DEBUG_CALLER_PC 0
+#endif
+
+// The thread closure walks threads to collect per-thread
+// memory recorders at NMT sync point
+class SyncThreadRecorderClosure : public ThreadClosure {
+ private:
+ int _thread_count;
+
+ public:
+ SyncThreadRecorderClosure() {
+ _thread_count =0;
+ }
+
+ void do_thread(Thread* thread);
+ int get_thread_count() const {
+ return _thread_count;
+ }
+};
+
+class BaselineOutputer;
+class MemSnapshot;
+class MemTrackWorker;
+class Thread;
+/*
+ * MemTracker is the 'gate' class to native memory tracking runtime.
+ */
+class MemTracker : AllStatic {
+ friend class MemTrackWorker;
+ friend class MemSnapshot;
+ friend class SyncThreadRecorderClosure;
+
+ // NMT state
+ enum NMTStates {
+ NMT_uninited, // not yet initialized
+ NMT_bootstrapping_single_thread, // bootstrapping, VM is in single thread mode
+ NMT_bootstrapping_multi_thread, // bootstrapping, VM is about to enter multi-thread mode
+ NMT_started, // NMT fully started
+ NMT_shutdown_pending, // shutdown pending
+ NMT_final_shutdown, // in final phase of shutdown
+ NMT_shutdown // shutdown
+ };
+
+
+ // native memory tracking level
+ enum NMTLevel {
+ NMT_off, // native memory tracking is off
+ NMT_summary, // don't track callsite
+ NMT_detail // track callsite also
+ };
+
+ public:
+ enum ShutdownReason {
+ NMT_shutdown_none, // no shutdown requested
+ NMT_shutdown_user, // user requested shutdown
+ NMT_normal, // normal shutdown, process exit
+ NMT_out_of_memory, // shutdown due to out of memory
+ NMT_initialization, // shutdown due to initialization failure
+ NMT_use_malloc_only, // can not combine NMT with UseMallocOnly flag
+ NMT_error_reporting, // shutdown by vmError::report_and_die()
+ NMT_out_of_generation, // running out of generation queue
+ NMT_sequence_overflow // overflow the sequence number
+ };
+
+ public:
+ // initialize NMT tracking level from command line options, called
+ // from VM command line parsing code
+ static void init_tracking_options(const char* option_line);
+
+ // if NMT is enabled to record memory activities
+ static inline bool is_on() {
+ return (_tracking_level >= NMT_summary &&
+ _state >= NMT_bootstrapping_single_thread);
+ }
+
+ // user readable reason for shutting down NMT
+ static const char* reason() {
+ switch(_reason) {
+ case NMT_shutdown_none:
+ return "Native memory tracking is not enabled";
+ case NMT_shutdown_user:
+ return "Native memory tracking has been shutdown by user";
+ case NMT_normal:
+ return "Native memory tracking has been shutdown due to process exiting";
+ case NMT_initialization:
+ return "Native memory tracking failed to initialize";
+ case NMT_error_reporting:
+ return "Native memory tracking has been shutdown due to error reporting";
+ case NMT_out_of_generation:
+ return "Native memory tracking has been shutdown due to running out of generation buffer";
+ case NMT_sequence_overflow:
+ return "Native memory tracking has been shutdown due to overflow the sequence number";
+ case NMT_use_malloc_only:
+ return "Native memory tracking is not supported when UseMallocOnly is on";
+ default:
+ ShouldNotReachHere();
+ return NULL;
+ }
+ }
+
+ // test if we can walk native stack
+ static bool can_walk_stack() {
+ // native stack is not walkable during bootstrapping on sparc
+#if defined(SPARC)
+ return (_state == NMT_started);
+#else
+ return (_state >= NMT_bootstrapping_single_thread && _state <= NMT_started);
+#endif
+ }
+
+ // if native memory tracking tracks callsite
+ static inline bool track_callsite() { return _tracking_level == NMT_detail; }
+
+ // shutdown native memory tracking capability. Native memory tracking
+ // can be shutdown by VM when it encounters low memory scenarios.
+ // Memory tracker should gracefully shutdown itself, and preserve the
+ // latest memory statistics for post morten diagnosis.
+ static void shutdown(ShutdownReason reason);
+
+ // if there is shutdown requested
+ static inline bool shutdown_in_progress() {
+ return (_state >= NMT_shutdown_pending);
+ }
+
+ // bootstrap native memory tracking, so it can start to collect raw data
+ // before worker thread can start
+
+ // the first phase of bootstrapping, when VM still in single-threaded mode
+ static void bootstrap_single_thread();
+ // the second phase of bootstrapping, VM is about or already in multi-threaded mode
+ static void bootstrap_multi_thread();
+
+
+ // start() has to be called when VM still in single thread mode, but after
+ // command line option parsing is done.
+ static void start();
+
+ // record a 'malloc' call
+ static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
+ address pc = 0, Thread* thread = NULL) {
+ assert(is_on(), "check by caller");
+ if (NMT_CAN_TRACK(flags)) {
+ create_memory_record(addr, (flags|MemPointerRecord::malloc_tag()), size, pc, thread);
+ }
+ }
+ // record a 'free' call
+ static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) {
+ if (is_on() && NMT_CAN_TRACK(flags)) {
+ create_memory_record(addr, MemPointerRecord::free_tag(), 0, 0, thread);
+ }
+ }
+ // record a 'realloc' call
+ static inline void record_realloc(address old_addr, address new_addr, size_t size,
+ MEMFLAGS flags, address pc = 0, Thread* thread = NULL) {
+ if (is_on()) {
+ record_free(old_addr, flags, thread);
+ record_malloc(new_addr, size, flags, pc, thread);
+ }
+ }
+
+ // record arena size
+ static inline void record_arena_size(address addr, size_t size) {
+ // we add a positive offset to arena address, so we can have arena size record
+ // sorted after arena record
+ if (is_on() && !UseMallocOnly) {
+ create_memory_record((addr + sizeof(void*)), MemPointerRecord::arena_size_tag(), size,
+ 0, NULL);
+ }
+ }
+
+ // record a virtual memory 'reserve' call
+ static inline void record_virtual_memory_reserve(address addr, size_t size,
+ address pc = 0, Thread* thread = NULL) {
+ if (is_on()) {
+ assert(size > 0, "reserve szero size");
+ create_memory_record(addr, MemPointerRecord::virtual_memory_reserve_tag(),
+ size, pc, thread);
+ }
+ }
+
+ // record a virtual memory 'commit' call
+ static inline void record_virtual_memory_commit(address addr, size_t size,
+ address pc = 0, Thread* thread = NULL) {
+ if (is_on()) {
+ create_memory_record(addr, MemPointerRecord::virtual_memory_commit_tag(),
+ size, pc, thread);
+ }
+ }
+
+ // record a virtual memory 'uncommit' call
+ static inline void record_virtual_memory_uncommit(address addr, size_t size,
+ Thread* thread = NULL) {
+ if (is_on()) {
+ create_memory_record(addr, MemPointerRecord::virtual_memory_uncommit_tag(),
+ size, 0, thread);
+ }
+ }
+
+ // record a virtual memory 'release' call
+ static inline void record_virtual_memory_release(address addr, size_t size,
+ Thread* thread = NULL) {
+ if (is_on()) {
+ create_memory_record(addr, MemPointerRecord::virtual_memory_release_tag(),
+ size, 0, thread);
+ }
+ }
+
+ // record memory type on virtual memory base address
+ static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
+ Thread* thread = NULL) {
+ if (is_on()) {
+ assert(base > 0, "wrong base address");
+ assert((flags & (~mt_masks)) == 0, "memory type only");
+ create_memory_record(base, (flags | MemPointerRecord::virtual_memory_type_tag()),
+ 0, 0, thread);
+ }
+ }
+
+
+ // create memory baseline of current memory snapshot
+ static bool baseline();
+ // is there a memory baseline
+ static bool has_baseline() {
+ return _baseline.baselined();
+ }
+
+ // print memory usage from current snapshot
+ static bool print_memory_usage(BaselineOutputer& out, size_t unit,
+ bool summary_only = true);
+ // compare memory usage between current snapshot and baseline
+ static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
+ bool summary_only = true);
+
+ // sync is called within global safepoint to synchronize nmt data
+ static void sync();
+
+ // called when a thread is about to exit
+ static void thread_exiting(JavaThread* thread);
+
+ // retrieve global snapshot
+ static MemSnapshot* get_snapshot() {
+ assert(is_on(), "native memory tracking is off");
+ if (shutdown_in_progress()) {
+ return NULL;
+ }
+ return _snapshot;
+ }
+
+ // print tracker stats
+ NOT_PRODUCT(static void print_tracker_stats(outputStream* st);)
+ NOT_PRODUCT(static void walk_stack(int toSkip, char* buf, int len);)
+
+ private:
+ // start native memory tracking worker thread
+ static bool start_worker();
+
+ // called by worker thread to complete shutdown process
+ static void final_shutdown();
+
+ protected:
+ // retrieve per-thread recorder of the specified thread.
+ // if the recorder is full, it will be enqueued to overflow
+ // queue, a new recorder is acquired from recorder pool or a
+ // new instance is created.
+ // when thread == NULL, it means global recorder
+ static MemRecorder* get_thread_recorder(JavaThread* thread);
+
+ // per-thread recorder pool
+ static void release_thread_recorder(MemRecorder* rec);
+ static void delete_all_pooled_recorders();
+
+ // pending recorder queue. Recorders are queued to pending queue
+ // when they are overflowed or collected at nmt sync point.
+ static void enqueue_pending_recorder(MemRecorder* rec);
+ static MemRecorder* get_pending_recorders();
+ static void delete_all_pending_recorders();
+
+ private:
+ // retrieve a pooled memory record or create new one if there is not
+ // one available
+ static MemRecorder* get_new_or_pooled_instance();
+ static void create_memory_record(address addr, MEMFLAGS type,
+ size_t size, address pc, Thread* thread);
+ static void create_record_in_recorder(address addr, MEMFLAGS type,
+ size_t size, address pc, Thread* thread);
+
+ private:
+ // global memory snapshot
+ static MemSnapshot* _snapshot;
+
+ // a memory baseline of snapshot
+ static MemBaseline _baseline;
+
+ // query lock
+ static Mutex _query_lock;
+
+ // a thread can start to allocate memory before it is attached
+ // to VM 'Thread', those memory activities are recorded here.
+ // ThreadCritical is required to guard this global recorder.
+ static MemRecorder* _global_recorder;
+
+ // main thread id
+ debug_only(static intx _main_thread_tid;)
+
+ // pending recorders to be merged
+ static volatile MemRecorder* _merge_pending_queue;
+
+ NOT_PRODUCT(static volatile jint _pending_recorder_count;)
+
+ // pooled memory recorders
+ static volatile MemRecorder* _pooled_recorders;
+
+ // memory recorder pool management, uses following
+ // counter to determine if a released memory recorder
+ // should be pooled
+
+ // latest thread count
+ static int _thread_count;
+ // pooled recorder count
+ static volatile jint _pooled_recorder_count;
+
+
+ // worker thread to merge pending recorders into snapshot
+ static MemTrackWorker* _worker_thread;
+
+ // how many safepoints we skipped without entering sync point
+ static int _sync_point_skip_count;
+
+ // if the tracker is properly intialized
+ static bool _is_tracker_ready;
+ // tracking level (off, summary and detail)
+ static enum NMTLevel _tracking_level;
+
+ // current nmt state
+ static volatile enum NMTStates _state;
+ // the reason for shutting down nmt
+ static enum ShutdownReason _reason;
+};
+
+#endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP
--- a/hotspot/src/share/vm/services/memoryManager.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/memoryManager.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -166,15 +166,15 @@
GCStatInfo::GCStatInfo(int num_pools) {
// initialize the arrays for memory usage
- _before_gc_usage_array = (MemoryUsage*) NEW_C_HEAP_ARRAY(MemoryUsage, num_pools);
- _after_gc_usage_array = (MemoryUsage*) NEW_C_HEAP_ARRAY(MemoryUsage, num_pools);
+ _before_gc_usage_array = (MemoryUsage*) NEW_C_HEAP_ARRAY(MemoryUsage, num_pools, mtInternal);
+ _after_gc_usage_array = (MemoryUsage*) NEW_C_HEAP_ARRAY(MemoryUsage, num_pools, mtInternal);
_usage_array_size = num_pools;
clear();
}
GCStatInfo::~GCStatInfo() {
- FREE_C_HEAP_ARRAY(MemoryUsage*, _before_gc_usage_array);
- FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array);
+ FREE_C_HEAP_ARRAY(MemoryUsage*, _before_gc_usage_array, mtInternal);
+ FREE_C_HEAP_ARRAY(MemoryUsage*, _after_gc_usage_array, mtInternal);
}
void GCStatInfo::set_gc_usage(int pool_index, MemoryUsage usage, bool before_gc) {
@@ -214,8 +214,8 @@
void GCMemoryManager::initialize_gc_stat_info() {
assert(MemoryService::num_memory_pools() > 0, "should have one or more memory pools");
- _last_gc_stat = new(ResourceObj::C_HEAP) GCStatInfo(MemoryService::num_memory_pools());
- _current_gc_stat = new(ResourceObj::C_HEAP) GCStatInfo(MemoryService::num_memory_pools());
+ _last_gc_stat = new(ResourceObj::C_HEAP, mtGC) GCStatInfo(MemoryService::num_memory_pools());
+ _current_gc_stat = new(ResourceObj::C_HEAP, mtGC) GCStatInfo(MemoryService::num_memory_pools());
// tracking concurrent collections we need two objects: one to update, and one to
// hold the publicly available "last (completed) gc" information.
}
--- a/hotspot/src/share/vm/services/memoryManager.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/memoryManager.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
class GCMemoryManager;
class OopClosure;
-class MemoryManager : public CHeapObj {
+class MemoryManager : public CHeapObj<mtInternal> {
private:
enum {
max_num_pools = 10
--- a/hotspot/src/share/vm/services/memoryPool.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/memoryPool.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -50,7 +50,7 @@
class PermGen;
class ThresholdSupport;
-class MemoryPool : public CHeapObj {
+class MemoryPool : public CHeapObj<mtInternal> {
friend class MemoryManager;
public:
enum PoolType {
--- a/hotspot/src/share/vm/services/memoryService.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/memoryService.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -58,9 +58,9 @@
#endif
GrowableArray<MemoryPool*>* MemoryService::_pools_list =
- new (ResourceObj::C_HEAP) GrowableArray<MemoryPool*>(init_pools_list_size, true);
+ new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryPool*>(init_pools_list_size, true);
GrowableArray<MemoryManager*>* MemoryService::_managers_list =
- new (ResourceObj::C_HEAP) GrowableArray<MemoryManager*>(init_managers_list_size, true);
+ new (ResourceObj::C_HEAP, mtInternal) GrowableArray<MemoryManager*>(init_managers_list_size, true);
GCMemoryManager* MemoryService::_minor_gc_manager = NULL;
GCMemoryManager* MemoryService::_major_gc_manager = NULL;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/nmtDCmd.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 "services/nmtDCmd.hpp"
+#include "services/memReporter.hpp"
+#include "services/memTracker.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+NMTDCmd::NMTDCmd(outputStream* output,
+ bool heap): DCmdWithParser(output, heap),
+ _summary("summary", "request runtime to report current memory summary, " \
+ "which includes total reserved and committed memory, along " \
+ "with memory usage summary by each subsytem.",
+ "BOOLEAN", false, "false"),
+ _detail("detail", "request runtime to report memory allocation >= "
+ "1K by each callsite.",
+ "BOOLEAN", false, "false"),
+ _baseline("baseline", "request runtime to baseline current memory usage, " \
+ "so it can be compared against in later time.",
+ "BOOLEAN", false, "false"),
+ _summary_diff("summary.diff", "request runtime to report memory summary " \
+ "comparison against previous baseline.",
+ "BOOLEAN", false, "false"),
+ _detail_diff("detail.diff", "request runtime to report memory detail " \
+ "comparison against previous baseline, which shows the memory " \
+ "allocation activities at different callsites.",
+ "BOOLEAN", false, "false"),
+ _shutdown("shutdown", "request runtime to shutdown itself and free the " \
+ "memory used by runtime.",
+ "BOOLEAN", false, "false"),
+#ifndef PRODUCT
+ _debug("debug", "print tracker statistics. Debug only, not thread safe", \
+ "BOOLEAN", false, "false"),
+#endif
+ _scale("scale", "Memory usage in which scale, KB, MB or GB",
+ "STRING", false, "KB") {
+ _dcmdparser.add_dcmd_option(&_summary);
+ _dcmdparser.add_dcmd_option(&_detail);
+ _dcmdparser.add_dcmd_option(&_baseline);
+ _dcmdparser.add_dcmd_option(&_summary_diff);
+ _dcmdparser.add_dcmd_option(&_detail_diff);
+ _dcmdparser.add_dcmd_option(&_shutdown);
+#ifndef PRODUCT
+ _dcmdparser.add_dcmd_option(&_debug);
+#endif
+ _dcmdparser.add_dcmd_option(&_scale);
+}
+
+void NMTDCmd::execute(TRAPS) {
+ const char* scale_value = _scale.value();
+ size_t scale_unit;
+ if (strcmp(scale_value, "KB") == 0 || strcmp(scale_value, "kb") == 0) {
+ scale_unit = K;
+ } else if (strcmp(scale_value, "MB") == 0 ||
+ strcmp(scale_value, "mb") == 0) {
+ scale_unit = M;
+ } else if (strcmp(scale_value, "GB") == 0 ||
+ strcmp(scale_value, "gb") == 0) {
+ scale_unit = G;
+ } else {
+ output()->print_cr("Incorrect scale value: %s", scale_value);
+ return;
+ }
+
+ int nopt = 0;
+ if(_summary.is_set()) { ++nopt; }
+ if(_detail.is_set()) { ++nopt; }
+ if(_baseline.is_set()) { ++nopt; }
+ if(_summary_diff.is_set()) { ++nopt; }
+ if(_detail_diff.is_set()) { ++nopt; }
+ if(_shutdown.is_set()) { ++nopt; }
+#ifndef PRODUCT
+ if(_debug.is_set()) { ++nopt; }
+#endif
+
+ if(nopt > 1) {
+ output()->print_cr("At most one of the following option can be specified: " \
+ "summary, detail, baseline, summary.diff, detail.diff, shutdown"
+#ifndef PRODUCT
+ " ,debug"
+#endif
+ );
+ return;
+ }
+
+ if(nopt == 0) {
+ _summary.set_value(true);
+ }
+
+#ifndef PRODUCT
+ if (_debug.value()) {
+ output()->print_cr("debug command is NOT thread-safe, may cause crash");
+ MemTracker::print_tracker_stats(output());
+ return;
+ }
+#endif
+
+ // native memory tracking has to be on
+ if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
+ // if it is not on, what's the reason?
+ output()->print_cr(MemTracker::reason());
+ return;
+ }
+
+ if (_summary.value()) {
+ BaselineTTYOutputer outputer(output());
+ MemTracker::print_memory_usage(outputer, scale_unit, true);
+ } else if (_detail.value()) {
+ BaselineTTYOutputer outputer(output());
+ MemTracker::print_memory_usage(outputer, scale_unit, false);
+ } else if (_baseline.value()) {
+ if (MemTracker::baseline()) {
+ output()->print_cr("Successfully baselined.");
+ } else {
+ output()->print_cr("Baseline failed.");
+ }
+ } else if (_summary_diff.value()) {
+ if (MemTracker::has_baseline()) {
+ BaselineTTYOutputer outputer(output());
+ MemTracker::compare_memory_usage(outputer, scale_unit, true);
+ } else {
+ output()->print_cr("No baseline to compare, run 'baseline' command first");
+ }
+ } else if (_detail_diff.value()) {
+ if (MemTracker::has_baseline()) {
+ BaselineTTYOutputer outputer(output());
+ MemTracker::compare_memory_usage(outputer, scale_unit, false);
+ } else {
+ output()->print_cr("No baseline to compare to, run 'baseline' command first");
+ }
+ } else if (_shutdown.value()) {
+ MemTracker::shutdown(MemTracker::NMT_shutdown_user);
+ output()->print_cr("Shutdown is in progress, it will take a few moments to " \
+ "completely shutdown");
+ } else {
+ ShouldNotReachHere();
+ output()->print_cr("Unknown command");
+ }
+}
+
+int NMTDCmd::num_arguments() {
+ ResourceMark rm;
+ NMTDCmd* dcmd = new NMTDCmd(NULL, false);
+ if (dcmd != NULL) {
+ DCmdMark mark(dcmd);
+ return dcmd->_dcmdparser.num_arguments();
+ } else {
+ return 0;
+ }
+}
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/services/nmtDCmd.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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_SERVICES_NMT_DCMD_HPP
+#define SHARE_VM_SERVICES_NMT_DCMD_HPP
+
+#include "services/diagnosticArgument.hpp"
+#include "services/diagnosticFramework.hpp"
+
+/**
+ * Native memory tracking DCmd implementation
+ */
+class NMTDCmd: public DCmdWithParser {
+ protected:
+ DCmdArgument<bool> _summary;
+ DCmdArgument<bool> _detail;
+ DCmdArgument<bool> _baseline;
+ DCmdArgument<bool> _summary_diff;
+ DCmdArgument<bool> _detail_diff;
+ DCmdArgument<bool> _shutdown;
+#ifndef PRODUCT
+ DCmdArgument<bool> _debug;
+#endif
+ DCmdArgument<char*> _scale;
+
+ public:
+ NMTDCmd(outputStream* output, bool heap);
+ static const char* name() { return "VM.native_memory"; }
+ static const char* description() {
+ return "Print native memory usage";
+ }
+ static const char* impact() {
+ return "Medium:";
+ }
+ static int num_arguments();
+ virtual void execute(TRAPS);
+};
+
+#endif // SHARE_VM_SERVICES_NMT_DCMD_HPP
--- a/hotspot/src/share/vm/services/threadService.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/threadService.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -437,7 +437,7 @@
GrowableArray<MonitorInfo*>* list = jvf->locked_monitors();
int length = list->length();
if (length > 0) {
- _locked_monitors = new (ResourceObj::C_HEAP) GrowableArray<oop>(length, true);
+ _locked_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(length, true);
for (int i = 0; i < length; i++) {
MonitorInfo* monitor = list->at(i);
assert(monitor->owner(), "This monitor must have an owning object");
@@ -491,11 +491,11 @@
ThreadStackTrace::ThreadStackTrace(JavaThread* t, bool with_locked_monitors) {
_thread = t;
- _frames = new (ResourceObj::C_HEAP) GrowableArray<StackFrameInfo*>(INITIAL_ARRAY_SIZE, true);
+ _frames = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<StackFrameInfo*>(INITIAL_ARRAY_SIZE, true);
_depth = 0;
_with_locked_monitors = with_locked_monitors;
if (_with_locked_monitors) {
- _jni_locked_monitors = new (ResourceObj::C_HEAP) GrowableArray<oop>(INITIAL_ARRAY_SIZE, true);
+ _jni_locked_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<oop>(INITIAL_ARRAY_SIZE, true);
} else {
_jni_locked_monitors = NULL;
}
@@ -689,7 +689,7 @@
ThreadConcurrentLocks::ThreadConcurrentLocks(JavaThread* thread) {
_thread = thread;
- _owned_locks = new (ResourceObj::C_HEAP) GrowableArray<instanceOop>(INITIAL_ARRAY_SIZE, true);
+ _owned_locks = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<instanceOop>(INITIAL_ARRAY_SIZE, true);
_next = NULL;
}
@@ -803,7 +803,7 @@
DeadlockCycle::DeadlockCycle() {
_is_deadlock = false;
- _threads = new (ResourceObj::C_HEAP) GrowableArray<JavaThread*>(INITIAL_ARRAY_SIZE, true);
+ _threads = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JavaThread*>(INITIAL_ARRAY_SIZE, true);
_next = NULL;
}
--- a/hotspot/src/share/vm/services/threadService.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/services/threadService.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -116,7 +116,7 @@
};
// Per-thread Statistics for synchronization
-class ThreadStatistics : public CHeapObj {
+class ThreadStatistics : public CHeapObj<mtInternal> {
private:
// The following contention statistics are only updated by
// the thread owning these statistics when contention occurs.
@@ -186,7 +186,7 @@
};
// Thread snapshot to represent the thread state and statistics
-class ThreadSnapshot : public CHeapObj {
+class ThreadSnapshot : public CHeapObj<mtInternal> {
private:
JavaThread* _thread;
oop _threadObj;
@@ -244,7 +244,7 @@
void oops_do(OopClosure* f);
};
-class ThreadStackTrace : public CHeapObj {
+class ThreadStackTrace : public CHeapObj<mtInternal> {
private:
JavaThread* _thread;
int _depth; // number of stack frames added
@@ -275,7 +275,7 @@
// StackFrameInfo for keeping methodOop and bci during
// stack walking for later construction of StackTraceElement[]
// Java instances
-class StackFrameInfo : public CHeapObj {
+class StackFrameInfo : public CHeapObj<mtInternal> {
private:
methodOop _method;
int _bci;
@@ -299,7 +299,7 @@
void print_on(outputStream* st) const;
};
-class ThreadConcurrentLocks : public CHeapObj {
+class ThreadConcurrentLocks : public CHeapObj<mtInternal> {
private:
GrowableArray<instanceOop>* _owned_locks;
ThreadConcurrentLocks* _next;
@@ -356,7 +356,7 @@
void oops_do(OopClosure* f);
};
-class DeadlockCycle : public CHeapObj {
+class DeadlockCycle : public CHeapObj<mtInternal> {
private:
bool _is_deadlock;
GrowableArray<JavaThread*>* _threads;
--- a/hotspot/src/share/vm/utilities/array.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/array.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -49,7 +49,7 @@
void ResourceArray::sort(size_t esize, ftype f) {
if (!is_empty()) qsort(_data, length(), esize, f);
}
-void CHeapArray::sort(size_t esize, ftype f) {
+template <MEMFLAGS F> void CHeapArray<F>::sort(size_t esize, ftype f) {
if (!is_empty()) qsort(_data, length(), esize, f);
}
@@ -70,14 +70,14 @@
}
-void CHeapArray::expand(size_t esize, int i, int& size) {
+template <MEMFLAGS F> void CHeapArray<F>::expand(size_t esize, int i, int& size) {
// determine new size
if (size == 0) size = 4; // prevent endless loop
while (i >= size) size *= 2;
// allocate and initialize new data section
- void* data = NEW_C_HEAP_ARRAY(char*, esize * size);
+ void* data = NEW_C_HEAP_ARRAY(char*, esize * size, F);
memcpy(data, _data, esize * length());
- FREE_C_HEAP_ARRAY(char*, _data);
+ FREE_C_HEAP_ARRAY(char*, _data, F);
_data = data;
}
@@ -91,7 +91,7 @@
memmove(dst, src, cnt);
}
-void CHeapArray::remove_at(size_t esize, int i) {
+template <MEMFLAGS F> void CHeapArray<F>::remove_at(size_t esize, int i) {
assert(0 <= i && i < length(), "index out of bounds");
_length--;
void* dst = (char*)_data + i*esize;
--- a/hotspot/src/share/vm/utilities/array.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/array.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -79,7 +79,7 @@
};
-class CHeapArray: public CHeapObj {
+template <MEMFLAGS F>class CHeapArray: public CHeapObj<F> {
protected:
int _length; // the number of array elements
void* _data; // the array memory
@@ -94,7 +94,7 @@
CHeapArray(size_t esize, int length) {
assert(length >= 0, "illegal length");
_length = length;
- _data = (void*) NEW_C_HEAP_ARRAY(char *, esize * length);
+ _data = (void*) NEW_C_HEAP_ARRAY(char *, esize * length, F);
}
#ifdef ASSERT
--- a/hotspot/src/share/vm/utilities/bitMap.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/bitMap.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -65,8 +65,8 @@
if (in_resource_area) {
_map = NEW_RESOURCE_ARRAY(bm_word_t, new_size_in_words);
} else {
- if (old_map != NULL) FREE_C_HEAP_ARRAY(bm_word_t, _map);
- _map = NEW_C_HEAP_ARRAY(bm_word_t, new_size_in_words);
+ if (old_map != NULL) FREE_C_HEAP_ARRAY(bm_word_t, _map, mtInternal);
+ _map = NEW_C_HEAP_ARRAY(bm_word_t, new_size_in_words, mtInternal);
}
Copy::disjoint_words((HeapWord*)old_map, (HeapWord*) _map,
MIN2(old_size_in_words, new_size_in_words));
@@ -469,7 +469,7 @@
void BitMap::init_pop_count_table() {
if (_pop_count_table == NULL) {
- BitMap::idx_t *table = NEW_C_HEAP_ARRAY(idx_t, 256);
+ BitMap::idx_t *table = NEW_C_HEAP_ARRAY(idx_t, 256, mtInternal);
for (uint i = 0; i < 256; i++) {
table[i] = num_set_bits(i);
}
@@ -479,7 +479,7 @@
(intptr_t) NULL_WORD);
if (res != NULL_WORD) {
guarantee( _pop_count_table == (void*) res, "invariant" );
- FREE_C_HEAP_ARRAY(bm_word_t, table);
+ FREE_C_HEAP_ARRAY(bm_word_t, table, mtInternal);
}
}
}
--- a/hotspot/src/share/vm/utilities/decoder.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/decoder.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -29,7 +29,7 @@
#include "memory/allocation.hpp"
#include "runtime/mutex.hpp"
-class AbstractDecoder : public CHeapObj {
+class AbstractDecoder : public CHeapObj<mtInternal> {
public:
// status code for decoding native C frame
enum decoder_status {
--- a/hotspot/src/share/vm/utilities/elfFile.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/elfFile.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -47,7 +47,7 @@
m_status = NullDecoder::no_error;
int len = strlen(filepath) + 1;
- m_filepath = (const char*)os::malloc(len * sizeof(char));
+ m_filepath = (const char*)os::malloc(len * sizeof(char), mtInternal);
if (m_filepath != NULL) {
strcpy((char*)m_filepath, filepath);
m_file = fopen(filepath, "r");
--- a/hotspot/src/share/vm/utilities/elfFile.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/elfFile.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -82,7 +82,7 @@
// in "error" state, so there are scenarios, lookup will fail. We want this
// part of code to be very defensive, and bait out if anything went wrong.
-class ElfFile: public CHeapObj {
+class ElfFile: public CHeapObj<mtInternal> {
friend class ElfDecoder;
public:
ElfFile(const char* filepath);
--- a/hotspot/src/share/vm/utilities/elfStringTable.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/elfStringTable.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -42,7 +42,7 @@
// try to load the string table
long cur_offset = ftell(file);
- m_table = (char*)os::malloc(sizeof(char) * shdr.sh_size);
+ m_table = (char*)os::malloc(sizeof(char) * shdr.sh_size, mtInternal);
if (m_table != NULL) {
// if there is an error, mark the error
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
--- a/hotspot/src/share/vm/utilities/elfStringTable.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/elfStringTable.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -35,7 +35,7 @@
// The string table represents a string table section in an elf file.
// Whenever there is enough memory, it will load whole string table as
// one blob. Otherwise, it will load string from file when requested.
-class ElfStringTable: CHeapObj {
+class ElfStringTable: CHeapObj<mtInternal> {
friend class ElfFile;
public:
ElfStringTable(FILE* file, Elf_Shdr shdr, int index);
--- a/hotspot/src/share/vm/utilities/elfSymbolTable.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/elfSymbolTable.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
long cur_offset = ftell(file);
if (cur_offset != -1) {
// call malloc so we can back up if memory allocation fails.
- m_symbols = (Elf_Sym*)os::malloc(shdr.sh_size);
+ m_symbols = (Elf_Sym*)os::malloc(shdr.sh_size, mtInternal);
if (m_symbols) {
if (fseek(file, shdr.sh_offset, SEEK_SET) ||
fread((void*)m_symbols, shdr.sh_size, 1, file) != 1 ||
--- a/hotspot/src/share/vm/utilities/elfSymbolTable.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/elfSymbolTable.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -38,7 +38,7 @@
* of the elf file into memory. Otherwise, it will walk the section in file
* to look up the symbol that nearest the given address.
*/
-class ElfSymbolTable: public CHeapObj {
+class ElfSymbolTable: public CHeapObj<mtInternal> {
friend class ElfFile;
public:
ElfSymbolTable(FILE* file, Elf_Shdr shdr);
--- a/hotspot/src/share/vm/utilities/events.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/events.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -46,7 +46,7 @@
// crash time. This is a very generic interface that is mainly here
// for completeness. Normally the templated EventLogBase would be
// subclassed to provide different log types.
-class EventLog : public CHeapObj {
+class EventLog : public CHeapObj<mtInternal> {
friend class Events;
private:
--- a/hotspot/src/share/vm/utilities/exceptions.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/exceptions.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -57,7 +57,7 @@
// field of the Thread class w/o having access to the Thread's interface (for
// include hierachy reasons).
-class ThreadShadow: public CHeapObj {
+class ThreadShadow: public CHeapObj<mtThread> {
friend class VMStructs;
protected:
--- a/hotspot/src/share/vm/utilities/growableArray.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/growableArray.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -61,7 +61,7 @@
if (on_stack()) {
return (void*)resource_allocate_bytes(byte_size);
} else if (on_C_heap()) {
- return (void*)AllocateHeap(byte_size, "GrET in " __FILE__);
+ return (void*)AllocateHeap(byte_size, _memflags);
} else {
return _arena->Amalloc(byte_size);
}
--- a/hotspot/src/share/vm/utilities/growableArray.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -86,6 +86,9 @@
// 0 means default ResourceArea
// 1 means on C heap
// otherwise, allocate in _arena
+
+ MEMFLAGS _memflags; // memory type if allocation in C heap
+
#ifdef ASSERT
int _nesting; // resource area nesting at creation
void set_nesting();
@@ -102,9 +105,14 @@
// This GA will use the resource stack for storage if c_heap==false,
// Else it will use the C heap. Use clear_and_deallocate to avoid leaks.
- GenericGrowableArray(int initial_size, int initial_len, bool c_heap) {
+ GenericGrowableArray(int initial_size, int initial_len, bool c_heap, MEMFLAGS flags = mtNone) {
_len = initial_len;
_max = initial_size;
+ _memflags = flags;
+
+ // memory type has to be specified for C heap allocation
+ assert(!(c_heap && flags == mtNone), "memory type not specified for C heap object");
+
assert(_len >= 0 && _len <= _max, "initial_len too big");
_arena = (c_heap ? (Arena*)1 : NULL);
set_nesting();
@@ -121,6 +129,8 @@
_max = initial_size;
assert(_len >= 0 && _len <= _max, "initial_len too big");
_arena = arena;
+ _memflags = mtNone;
+
assert(on_arena(), "arena has taken on reserved value 0 or 1");
// Relax next assert to allow object allocation on resource area,
// on stack or embedded into an other object.
@@ -152,12 +162,14 @@
for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
}
- GrowableArray(int initial_size, bool C_heap = false) : GenericGrowableArray(initial_size, 0, C_heap) {
+ GrowableArray(int initial_size, bool C_heap = false, MEMFLAGS F = mtInternal)
+ : GenericGrowableArray(initial_size, 0, C_heap, F) {
_data = (E*)raw_allocate(sizeof(E));
for (int i = 0; i < _max; i++) ::new ((void*)&_data[i]) E();
}
- GrowableArray(int initial_size, int initial_len, const E& filler, bool C_heap = false) : GenericGrowableArray(initial_size, initial_len, C_heap) {
+ GrowableArray(int initial_size, int initial_len, const E& filler, bool C_heap = false, MEMFLAGS memflags = mtInternal)
+ : GenericGrowableArray(initial_size, initial_len, C_heap, memflags) {
_data = (E*)raw_allocate(sizeof(E));
int i = 0;
for (; i < _len; i++) ::new ((void*)&_data[i]) E(filler);
--- a/hotspot/src/share/vm/utilities/hashtable.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/hashtable.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -23,6 +23,8 @@
*/
#include "precompiled.hpp"
+#include "classfile/altHashing.hpp"
+#include "classfile/javaClasses.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "memory/resourceArea.hpp"
@@ -33,11 +35,6 @@
#include "utilities/hashtable.inline.hpp"
-#ifndef USDT2
-HS_DTRACE_PROBE_DECL4(hs_private, hashtable__new_entry,
- void*, unsigned int, void*, void*);
-#endif /* !USDT2 */
-
// This is a generic hashtable, designed to be used for the symbol
// and string tables.
//
@@ -46,8 +43,8 @@
// %note:
// - HashtableEntrys are allocated in blocks to reduce the space overhead.
-BasicHashtableEntry* BasicHashtable::new_entry(unsigned int hashValue) {
- BasicHashtableEntry* entry;
+template <MEMFLAGS F> BasicHashtableEntry<F>* BasicHashtable<F>::new_entry(unsigned int hashValue) {
+ BasicHashtableEntry<F>* entry;
if (_free_list) {
entry = _free_list;
@@ -58,10 +55,10 @@
int len = _entry_size * block_size;
len = 1 << log2_intptr(len); // round down to power of 2
assert(len >= _entry_size, "");
- _first_free_entry = NEW_C_HEAP_ARRAY(char, len);
+ _first_free_entry = NEW_C_HEAP_ARRAY2(char, len, F, CURRENT_PC);
_end_block = _first_free_entry + len;
}
- entry = (BasicHashtableEntry*)_first_free_entry;
+ entry = (BasicHashtableEntry<F>*)_first_free_entry;
_first_free_entry += _entry_size;
}
@@ -71,29 +68,21 @@
}
-template <class T> HashtableEntry<T>* Hashtable<T>::new_entry(unsigned int hashValue, T obj) {
- HashtableEntry<T>* entry;
+template <class T, MEMFLAGS F> HashtableEntry<T, F>* Hashtable<T, F>::new_entry(unsigned int hashValue, T obj) {
+ HashtableEntry<T, F>* entry;
- entry = (HashtableEntry<T>*)BasicHashtable::new_entry(hashValue);
+ entry = (HashtableEntry<T, F>*)BasicHashtable<F>::new_entry(hashValue);
entry->set_literal(obj);
-#ifndef USDT2
- HS_DTRACE_PROBE4(hs_private, hashtable__new_entry,
- this, hashValue, obj, entry);
-#else /* USDT2 */
- HS_PRIVATE_HASHTABLE_NEW_ENTRY(
- this, hashValue, (uintptr_t) obj, entry);
-#endif /* USDT2 */
return entry;
}
-
// Check to see if the hashtable is unbalanced. The caller set a flag to
// rehash at the next safepoint. If this bucket is 60 times greater than the
// expected average bucket length, it's an unbalanced hashtable.
// This is somewhat an arbitrary heuristic but if one bucket gets to
// rehash_count which is currently 100, there's probably something wrong.
-bool BasicHashtable::check_rehash_table(int count) {
+template <MEMFLAGS F> bool BasicHashtable<F>::check_rehash_table(int count) {
assert(table_size() != 0, "underflow");
if (count > (((double)number_of_entries()/(double)table_size())*rehash_multiple)) {
// Set a flag for the next safepoint, which should be at some guaranteed
@@ -103,17 +92,38 @@
return false;
}
+template <class T, MEMFLAGS F> jint Hashtable<T, F>::_seed = 0;
+
+template <class T, MEMFLAGS F> unsigned int Hashtable<T, F>::new_hash(Symbol* sym) {
+ ResourceMark rm;
+ // Use alternate hashing algorithm on this symbol.
+ return AltHashing::murmur3_32(seed(), (const jbyte*)sym->as_C_string(), sym->utf8_length());
+}
+
+template <class T, MEMFLAGS F> unsigned int Hashtable<T, F>::new_hash(oop string) {
+ ResourceMark rm;
+ int length;
+ jchar* chars = java_lang_String::as_unicode_string(string, length);
+ // Use alternate hashing algorithm on the string
+ return AltHashing::murmur3_32(seed(), chars, length);
+}
+
// Create a new table and using alternate hash code, populate the new table
// with the existing elements. This can be used to change the hash code
// and could in the future change the size of the table.
-template <class T> void Hashtable<T>::move_to(Hashtable<T>* new_table) {
- int saved_entry_count = number_of_entries();
+template <class T, MEMFLAGS F> void Hashtable<T, F>::move_to(Hashtable<T, F>* new_table) {
+
+ // Initialize the global seed for hashing.
+ _seed = AltHashing::compute_seed();
+ assert(seed() != 0, "shouldn't be zero");
+
+ int saved_entry_count = this->number_of_entries();
// Iterate through the table and create a new entry for the new table
for (int i = 0; i < new_table->table_size(); ++i) {
- for (HashtableEntry<T>* p = bucket(i); p != NULL; ) {
- HashtableEntry<T>* next = p->next();
+ for (HashtableEntry<T, F>* p = bucket(i); p != NULL; ) {
+ HashtableEntry<T, F>* next = p->next();
T string = p->literal();
// Use alternate hashing algorithm on the symbol in the first table
unsigned int hashValue = new_hash(string);
@@ -141,16 +151,16 @@
// for the elements has been used in a new table and is not
// destroyed. The memory reuse will benefit resizing the SystemDictionary
// to avoid a memory allocation spike at safepoint.
- free_buckets();
+ BasicHashtable<F>::free_buckets();
}
-void BasicHashtable::free_buckets() {
+template <MEMFLAGS F> void BasicHashtable<F>::free_buckets() {
if (NULL != _buckets) {
// Don't delete the buckets in the shared space. They aren't
// allocated by os::malloc
if (!UseSharedSpaces ||
!FileMapInfo::current_info()->is_in_shared_space(_buckets)) {
- FREE_C_HEAP_ARRAY(HashtableBucket, _buckets);
+ FREE_C_HEAP_ARRAY(HashtableBucket, _buckets, F);
}
_buckets = NULL;
}
@@ -159,13 +169,13 @@
// Reverse the order of elements in the hash buckets.
-void BasicHashtable::reverse() {
+template <MEMFLAGS F> void BasicHashtable<F>::reverse() {
for (int i = 0; i < _table_size; ++i) {
- BasicHashtableEntry* new_list = NULL;
- BasicHashtableEntry* p = bucket(i);
+ BasicHashtableEntry<F>* new_list = NULL;
+ BasicHashtableEntry<F>* p = bucket(i);
while (p != NULL) {
- BasicHashtableEntry* next = p->next();
+ BasicHashtableEntry<F>* next = p->next();
p->set_next(new_list);
new_list = p;
p = next;
@@ -177,7 +187,7 @@
// Copy the table to the shared space.
-void BasicHashtable::copy_table(char** top, char* end) {
+template <MEMFLAGS F> void BasicHashtable<F>::copy_table(char** top, char* end) {
// Dump the hash table entries.
@@ -186,13 +196,13 @@
int i;
for (i = 0; i < _table_size; ++i) {
- for (BasicHashtableEntry** p = _buckets[i].entry_addr();
+ for (BasicHashtableEntry<F>** p = _buckets[i].entry_addr();
*p != NULL;
p = (*p)->next_addr()) {
if (*top + entry_size() > end) {
report_out_of_shared_space(SharedMiscData);
}
- *p = (BasicHashtableEntry*)memcpy(*top, *p, entry_size());
+ *p = (BasicHashtableEntry<F>*)memcpy(*top, *p, entry_size());
*top += entry_size();
}
}
@@ -201,7 +211,7 @@
// Set the shared bit.
for (i = 0; i < _table_size; ++i) {
- for (BasicHashtableEntry* p = bucket(i); p != NULL; p = p->next()) {
+ for (BasicHashtableEntry<F>* p = bucket(i); p != NULL; p = p->next()) {
p->set_shared();
}
}
@@ -211,15 +221,15 @@
// Reverse the order of elements in the hash buckets.
-template <class T> void Hashtable<T>::reverse(void* boundary) {
+template <class T, MEMFLAGS F> void Hashtable<T, F>::reverse(void* boundary) {
- for (int i = 0; i < table_size(); ++i) {
- HashtableEntry<T>* high_list = NULL;
- HashtableEntry<T>* low_list = NULL;
- HashtableEntry<T>* last_low_entry = NULL;
- HashtableEntry<T>* p = bucket(i);
+ for (int i = 0; i < this->table_size(); ++i) {
+ HashtableEntry<T, F>* high_list = NULL;
+ HashtableEntry<T, F>* low_list = NULL;
+ HashtableEntry<T, F>* last_low_entry = NULL;
+ HashtableEntry<T, F>* p = bucket(i);
while (p != NULL) {
- HashtableEntry<T>* next = p->next();
+ HashtableEntry<T, F>* next = p->next();
if ((void*)p->literal() >= boundary) {
p->set_next(high_list);
high_list = p;
@@ -244,8 +254,8 @@
// Dump the hash table buckets.
-void BasicHashtable::copy_buckets(char** top, char* end) {
- intptr_t len = _table_size * sizeof(HashtableBucket);
+template <MEMFLAGS F> void BasicHashtable<F>::copy_buckets(char** top, char* end) {
+ intptr_t len = _table_size * sizeof(HashtableBucket<F>);
*(intptr_t*)(*top) = len;
*top += sizeof(intptr_t);
@@ -255,18 +265,18 @@
if (*top + len > end) {
report_out_of_shared_space(SharedMiscData);
}
- _buckets = (HashtableBucket*)memcpy(*top, _buckets, len);
+ _buckets = (HashtableBucket<F>*)memcpy(*top, _buckets, len);
*top += len;
}
#ifndef PRODUCT
-template <class T> void Hashtable<T>::print() {
+template <class T, MEMFLAGS F> void Hashtable<T, F>::print() {
ResourceMark rm;
- for (int i = 0; i < table_size(); i++) {
- HashtableEntry<T>* entry = bucket(i);
+ for (int i = 0; i < BasicHashtable<F>::table_size(); i++) {
+ HashtableEntry<T, F>* entry = bucket(i);
while(entry != NULL) {
tty->print("%d : ", i);
entry->literal()->print();
@@ -277,10 +287,10 @@
}
-void BasicHashtable::verify() {
+template <MEMFLAGS F> void BasicHashtable<F>::verify() {
int count = 0;
for (int i = 0; i < table_size(); i++) {
- for (BasicHashtableEntry* p = bucket(i); p != NULL; p = p->next()) {
+ for (BasicHashtableEntry<F>* p = bucket(i); p != NULL; p = p->next()) {
++count;
}
}
@@ -293,7 +303,7 @@
#ifdef ASSERT
-void BasicHashtable::verify_lookup_length(double load) {
+template <MEMFLAGS F> void BasicHashtable<F>::verify_lookup_length(double load) {
if ((double)_lookup_length / (double)_lookup_count > load * 2.0) {
warning("Performance bug: SystemDictionary lookup_count=%d "
"lookup_length=%d average=%lf load=%f",
@@ -303,10 +313,22 @@
}
#endif
-
// Explicitly instantiate these types
-template class Hashtable<constantPoolOop>;
-template class Hashtable<Symbol*>;
-template class Hashtable<klassOop>;
-template class Hashtable<oop>;
-
+template class Hashtable<constantPoolOop, mtClass>;
+template class Hashtable<Symbol*, mtSymbol>;
+template class Hashtable<klassOop, mtClass>;
+template class Hashtable<oop, mtClass>;
+#ifdef SOLARIS
+template class Hashtable<oop, mtSymbol>;
+#endif
+template class Hashtable<oopDesc*, mtSymbol>;
+template class Hashtable<Symbol*, mtClass>;
+template class HashtableEntry<Symbol*, mtSymbol>;
+template class HashtableEntry<Symbol*, mtClass>;
+template class HashtableEntry<oop, mtSymbol>;
+template class BasicHashtableEntry<mtSymbol>;
+template class BasicHashtableEntry<mtCode>;
+template class BasicHashtable<mtClass>;
+template class BasicHashtable<mtSymbol>;
+template class BasicHashtable<mtCode>;
+template class BasicHashtable<mtInternal>;
--- a/hotspot/src/share/vm/utilities/hashtable.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/hashtable.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -40,7 +40,7 @@
-class BasicHashtableEntry : public CHeapObj {
+template <MEMFLAGS F> class BasicHashtableEntry : public CHeapObj<F> {
friend class VMStructs;
private:
unsigned int _hash; // 32-bit hash for item
@@ -52,7 +52,7 @@
// shared entries will not change. New entries will always be
// unshared and since pointers are align, bit 0 will always remain 0
// with no extra effort.
- BasicHashtableEntry* _next;
+ BasicHashtableEntry<F>* _next;
// Windows IA64 compiler requires subclasses to be able to access these
protected:
@@ -69,19 +69,19 @@
void set_hash(unsigned int hash) { _hash = hash; }
unsigned int* hash_addr() { return &_hash; }
- static BasicHashtableEntry* make_ptr(BasicHashtableEntry* p) {
+ static BasicHashtableEntry<F>* make_ptr(BasicHashtableEntry<F>* p) {
return (BasicHashtableEntry*)((intptr_t)p & -2);
}
- BasicHashtableEntry* next() const {
+ BasicHashtableEntry<F>* next() const {
return make_ptr(_next);
}
- void set_next(BasicHashtableEntry* next) {
+ void set_next(BasicHashtableEntry<F>* next) {
_next = next;
}
- BasicHashtableEntry** next_addr() {
+ BasicHashtableEntry<F>** next_addr() {
return &_next;
}
@@ -90,13 +90,13 @@
}
void set_shared() {
- _next = (BasicHashtableEntry*)((intptr_t)_next | 1);
+ _next = (BasicHashtableEntry<F>*)((intptr_t)_next | 1);
}
};
-template <class T> class HashtableEntry : public BasicHashtableEntry {
+template <class T, MEMFLAGS F> class HashtableEntry : public BasicHashtableEntry<F> {
friend class VMStructs;
private:
T _literal; // ref to item in table.
@@ -108,20 +108,20 @@
void set_literal(T s) { _literal = s; }
HashtableEntry* next() const {
- return (HashtableEntry*)BasicHashtableEntry::next();
+ return (HashtableEntry*)BasicHashtableEntry<F>::next();
}
HashtableEntry** next_addr() {
- return (HashtableEntry**)BasicHashtableEntry::next_addr();
+ return (HashtableEntry**)BasicHashtableEntry<F>::next_addr();
}
};
-class HashtableBucket : public CHeapObj {
+template <MEMFLAGS F> class HashtableBucket : public CHeapObj<F> {
friend class VMStructs;
private:
// Instance variable
- BasicHashtableEntry* _entry;
+ BasicHashtableEntry<F>* _entry;
public:
// Accessing
@@ -129,21 +129,21 @@
// The following methods use order access methods to avoid race
// conditions in multiprocessor systems.
- BasicHashtableEntry* get_entry() const;
- void set_entry(BasicHashtableEntry* l);
+ BasicHashtableEntry<F>* get_entry() const;
+ void set_entry(BasicHashtableEntry<F>* l);
// The following method is not MT-safe and must be done under lock.
- BasicHashtableEntry** entry_addr() { return &_entry; }
+ BasicHashtableEntry<F>** entry_addr() { return &_entry; }
};
-class BasicHashtable : public CHeapObj {
+template <MEMFLAGS F> class BasicHashtable : public CHeapObj<F> {
friend class VMStructs;
public:
BasicHashtable(int table_size, int entry_size);
BasicHashtable(int table_size, int entry_size,
- HashtableBucket* buckets, int number_of_entries);
+ HashtableBucket<F>* buckets, int number_of_entries);
// Sharing support.
void copy_buckets(char** top, char* end);
@@ -162,8 +162,8 @@
private:
// Instance variables
int _table_size;
- HashtableBucket* _buckets;
- BasicHashtableEntry* _free_list;
+ HashtableBucket<F>* _buckets;
+ BasicHashtableEntry<F>* _free_list;
char* _first_free_entry;
char* _end_block;
int _entry_size;
@@ -188,20 +188,20 @@
int entry_size() const { return _entry_size; }
// The following method is MT-safe and may be used with caution.
- BasicHashtableEntry* bucket(int i);
+ BasicHashtableEntry<F>* bucket(int i);
// The following method is not MT-safe and must be done under lock.
- BasicHashtableEntry** bucket_addr(int i) { return _buckets[i].entry_addr(); }
+ BasicHashtableEntry<F>** bucket_addr(int i) { return _buckets[i].entry_addr(); }
// Table entry management
- BasicHashtableEntry* new_entry(unsigned int hashValue);
+ BasicHashtableEntry<F>* new_entry(unsigned int hashValue);
// Check that the table is unbalanced
bool check_rehash_table(int count);
// Used when moving the entry to another table
// Clean up links, but do not add to free_list
- void unlink_entry(BasicHashtableEntry* entry) {
+ void unlink_entry(BasicHashtableEntry<F>* entry) {
entry->set_next(NULL);
--_number_of_entries;
}
@@ -221,11 +221,11 @@
public:
int table_size() { return _table_size; }
- void set_entry(int index, BasicHashtableEntry* entry);
+ void set_entry(int index, BasicHashtableEntry<F>* entry);
- void add_entry(int index, BasicHashtableEntry* entry);
+ void add_entry(int index, BasicHashtableEntry<F>* entry);
- void free_entry(BasicHashtableEntry* entry);
+ void free_entry(BasicHashtableEntry<F>* entry);
int number_of_entries() { return _number_of_entries; }
@@ -233,16 +233,16 @@
};
-template <class T> class Hashtable : public BasicHashtable {
+template <class T, MEMFLAGS F> class Hashtable : public BasicHashtable<F> {
friend class VMStructs;
public:
Hashtable(int table_size, int entry_size)
- : BasicHashtable(table_size, entry_size) { }
+ : BasicHashtable<F>(table_size, entry_size) { }
Hashtable(int table_size, int entry_size,
- HashtableBucket* buckets, int number_of_entries)
- : BasicHashtable(table_size, entry_size, buckets, number_of_entries) { }
+ HashtableBucket<F>* buckets, int number_of_entries)
+ : BasicHashtable<F>(table_size, entry_size, buckets, number_of_entries) { }
// Debugging
void print() PRODUCT_RETURN;
@@ -264,35 +264,42 @@
}
// Table entry management
- HashtableEntry<T>* new_entry(unsigned int hashValue, T obj);
+ HashtableEntry<T, F>* new_entry(unsigned int hashValue, T obj);
// The following method is MT-safe and may be used with caution.
- HashtableEntry<T>* bucket(int i) {
- return (HashtableEntry<T>*)BasicHashtable::bucket(i);
+ HashtableEntry<T, F>* bucket(int i) {
+ return (HashtableEntry<T, F>*)BasicHashtable<F>::bucket(i);
}
// The following method is not MT-safe and must be done under lock.
- HashtableEntry<T>** bucket_addr(int i) {
- return (HashtableEntry<T>**)BasicHashtable::bucket_addr(i);
+ HashtableEntry<T, F>** bucket_addr(int i) {
+ return (HashtableEntry<T, F>**)BasicHashtable<F>::bucket_addr(i);
}
// Function to move these elements into the new table.
- void move_to(Hashtable<T>* new_table);
- virtual unsigned int new_hash(T) { ShouldNotReachHere(); return 0; } // should be overridden
+ void move_to(Hashtable<T, F>* new_table);
+ static bool use_alternate_hashcode() { return _seed != 0; }
+ static jint seed() { return _seed; }
+
+ private:
+ static jint _seed;
+
+ unsigned int new_hash(Symbol* s);
+ unsigned int new_hash(oop string);
};
// Verions of hashtable where two handles are used to compute the index.
-template <class T> class TwoOopHashtable : public Hashtable<T> {
+template <class T, MEMFLAGS F> class TwoOopHashtable : public Hashtable<T, F> {
friend class VMStructs;
protected:
TwoOopHashtable(int table_size, int entry_size)
- : Hashtable<T>(table_size, entry_size) {}
+ : Hashtable<T, F>(table_size, entry_size) {}
- TwoOopHashtable(int table_size, int entry_size, HashtableBucket* t,
+ TwoOopHashtable(int table_size, int entry_size, HashtableBucket<F>* t,
int number_of_entries)
- : Hashtable<T>(table_size, entry_size, t, number_of_entries) {}
+ : Hashtable<T, F>(table_size, entry_size, t, number_of_entries) {}
public:
unsigned int compute_hash(Symbol* name, Handle loader) {
--- a/hotspot/src/share/vm/utilities/hashtable.inline.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/hashtable.inline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -27,6 +27,7 @@
#include "memory/allocation.inline.hpp"
#include "utilities/hashtable.hpp"
+#include "utilities/dtrace.hpp"
// Inline function definitions for hashtable.hpp.
@@ -34,18 +35,18 @@
// Initialize a table.
-inline BasicHashtable::BasicHashtable(int table_size, int entry_size) {
+template <MEMFLAGS F> inline BasicHashtable<F>::BasicHashtable(int table_size, int entry_size) {
// Called on startup, no locking needed
initialize(table_size, entry_size, 0);
- _buckets = NEW_C_HEAP_ARRAY(HashtableBucket, table_size);
+ _buckets = NEW_C_HEAP_ARRAY2(HashtableBucket<F>, table_size, F, CURRENT_PC);
for (int index = 0; index < _table_size; index++) {
_buckets[index].clear();
}
}
-inline BasicHashtable::BasicHashtable(int table_size, int entry_size,
- HashtableBucket* buckets,
+template <MEMFLAGS F> inline BasicHashtable<F>::BasicHashtable(int table_size, int entry_size,
+ HashtableBucket<F>* buckets,
int number_of_entries) {
// Called on startup, no locking needed
initialize(table_size, entry_size, number_of_entries);
@@ -53,7 +54,7 @@
}
-inline void BasicHashtable::initialize(int table_size, int entry_size,
+template <MEMFLAGS F> inline void BasicHashtable<F>::initialize(int table_size, int entry_size,
int number_of_entries) {
// Called on startup, no locking needed
_table_size = table_size;
@@ -70,12 +71,12 @@
// The following method is MT-safe and may be used with caution.
-inline BasicHashtableEntry* BasicHashtable::bucket(int i) {
+template <MEMFLAGS F> inline BasicHashtableEntry<F>* BasicHashtable<F>::bucket(int i) {
return _buckets[i].get_entry();
}
-inline void HashtableBucket::set_entry(BasicHashtableEntry* l) {
+template <MEMFLAGS F> inline void HashtableBucket<F>::set_entry(BasicHashtableEntry<F>* l) {
// Warning: Preserve store ordering. The SystemDictionary is read
// without locks. The new SystemDictionaryEntry must be
// complete before other threads can be allowed to see it
@@ -84,27 +85,27 @@
}
-inline BasicHashtableEntry* HashtableBucket::get_entry() const {
+template <MEMFLAGS F> inline BasicHashtableEntry<F>* HashtableBucket<F>::get_entry() const {
// Warning: Preserve load ordering. The SystemDictionary is read
// without locks. The new SystemDictionaryEntry must be
// complete before other threads can be allowed to see it
// via a store to _buckets[index].
- return (BasicHashtableEntry*) OrderAccess::load_ptr_acquire(&_entry);
+ return (BasicHashtableEntry<F>*) OrderAccess::load_ptr_acquire(&_entry);
}
-inline void BasicHashtable::set_entry(int index, BasicHashtableEntry* entry) {
+template <MEMFLAGS F> inline void BasicHashtable<F>::set_entry(int index, BasicHashtableEntry<F>* entry) {
_buckets[index].set_entry(entry);
}
-inline void BasicHashtable::add_entry(int index, BasicHashtableEntry* entry) {
+template <MEMFLAGS F> inline void BasicHashtable<F>::add_entry(int index, BasicHashtableEntry<F>* entry) {
entry->set_next(bucket(index));
_buckets[index].set_entry(entry);
++_number_of_entries;
}
-inline void BasicHashtable::free_entry(BasicHashtableEntry* entry) {
+template <MEMFLAGS F> inline void BasicHashtable<F>::free_entry(BasicHashtableEntry<F>* entry) {
entry->set_next(_free_list);
_free_list = entry;
--_number_of_entries;
--- a/hotspot/src/share/vm/utilities/histogram.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/histogram.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -69,7 +69,7 @@
Histogram::Histogram(const char* title,int estimatedCount) {
_title = title;
- _elements = new (ResourceObj::C_HEAP) GrowableArray<HistogramElement*>(estimatedCount,true);
+ _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<HistogramElement*>(estimatedCount,true);
}
void Histogram::add_element(HistogramElement* element) {
--- a/hotspot/src/share/vm/utilities/histogram.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/histogram.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -77,7 +77,7 @@
#ifdef ASSERT
-class HistogramElement : public CHeapObj {
+class HistogramElement : public CHeapObj<mtInternal> {
protected:
jint _count;
const char* _name;
@@ -91,7 +91,7 @@
virtual int compare(HistogramElement* e1,HistogramElement* e2);
};
-class Histogram : public CHeapObj {
+class Histogram : public CHeapObj<mtInternal> {
protected:
GrowableArray<HistogramElement*>* _elements;
GrowableArray<HistogramElement*>* elements() { return _elements; }
--- a/hotspot/src/share/vm/utilities/intHisto.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/intHisto.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -27,7 +27,7 @@
IntHistogram::IntHistogram(int est, int max) : _max(max), _tot(0) {
assert(0 <= est && est <= max, "Preconditions");
- _elements = new (ResourceObj::C_HEAP) GrowableArray<int>(est, true);
+ _elements = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<int>(est, true);
guarantee(_elements != NULL, "alloc failure");
}
--- a/hotspot/src/share/vm/utilities/intHisto.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/intHisto.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -47,7 +47,7 @@
// relation) to a count.
-class IntHistogram : public CHeapObj {
+class IntHistogram : public CHeapObj<mtInternal> {
protected:
int _max;
int _tot;
--- a/hotspot/src/share/vm/utilities/numberSeq.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/numberSeq.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -133,13 +133,13 @@
TruncatedSeq::TruncatedSeq(int length, double alpha):
AbsSeq(alpha), _length(length), _next(0) {
- _sequence = NEW_C_HEAP_ARRAY(double, _length);
+ _sequence = NEW_C_HEAP_ARRAY(double, _length, mtInternal);
for (int i = 0; i < _length; ++i)
_sequence[i] = 0.0;
}
TruncatedSeq::~TruncatedSeq() {
- FREE_C_HEAP_ARRAY(double, _sequence);
+ FREE_C_HEAP_ARRAY(double, _sequence, mtGC);
}
void TruncatedSeq::add(double val) {
--- a/hotspot/src/share/vm/utilities/numberSeq.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/numberSeq.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -25,6 +25,8 @@
#ifndef SHARE_VM_UTILITIES_NUMBERSEQ_HPP
#define SHARE_VM_UTILITIES_NUMBERSEQ_HPP
+#include "memory/allocation.hpp"
+
/**
** This file contains a few classes that represent number sequence,
** x1, x2, x3, ..., xN, and can calculate their avg, max, and sd.
@@ -40,7 +42,7 @@
#define DEFAULT_ALPHA_VALUE 0.7
-class AbsSeq {
+class AbsSeq: public CHeapObj<mtInternal> {
private:
void init(double alpha);
--- a/hotspot/src/share/vm/utilities/ostream.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/ostream.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -384,7 +384,7 @@
if (_file != NULL) {
if (_need_close) fclose(_file);
_file = NULL;
- FREE_C_HEAP_ARRAY(char, _file_name);
+ FREE_C_HEAP_ARRAY(char, _file_name, mtInternal);
_file_name = NULL;
}
}
@@ -392,7 +392,7 @@
rotatingFileStream::rotatingFileStream(const char* file_name) {
_cur_file_num = 0;
_bytes_writen = 0L;
- _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10);
+ _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal);
jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num);
_file = fopen(_file_name, "w");
_need_close = true;
@@ -401,7 +401,7 @@
rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) {
_cur_file_num = 0;
_bytes_writen = 0L;
- _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10);
+ _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal);
jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num);
_file = fopen(_file_name, opentype);
_need_close = true;
@@ -524,7 +524,7 @@
}
// Create big enough buffer.
- char *buf = NEW_C_HEAP_ARRAY(char, buffer_length);
+ char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
strcpy(buf, "");
if (force_directory != NULL) {
@@ -549,7 +549,7 @@
// %%% Need a MutexLocker?
const char* log_name = LogFile != NULL ? LogFile : "hotspot.log";
const char* try_name = make_log_name(log_name, NULL);
- fileStream* file = new(ResourceObj::C_HEAP) fileStream(try_name);
+ fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
if (!file->is_open()) {
// Try again to open the file.
char warnbuf[O_BUFLEN*2];
@@ -557,18 +557,18 @@
"Warning: Cannot open log file: %s\n", try_name);
// Note: This feature is for maintainer use only. No need for L10N.
jio_print(warnbuf);
- FREE_C_HEAP_ARRAY(char, try_name);
+ FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
try_name = make_log_name("hs_pid%p.log", os::get_temp_directory());
jio_snprintf(warnbuf, sizeof(warnbuf),
"Warning: Forcing option -XX:LogFile=%s\n", try_name);
jio_print(warnbuf);
delete file;
- file = new(ResourceObj::C_HEAP) fileStream(try_name);
- FREE_C_HEAP_ARRAY(char, try_name);
+ file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name);
+ FREE_C_HEAP_ARRAY(char, try_name, mtInternal);
}
if (file->is_open()) {
_log_file = file;
- xmlStream* xs = new(ResourceObj::C_HEAP) xmlStream(file);
+ xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file);
_outer_xmlStream = xs;
if (this == tty) xtty = xs;
// Write XML header.
@@ -815,7 +815,7 @@
void ostream_init() {
if (defaultStream::instance == NULL) {
- defaultStream::instance = new(ResourceObj::C_HEAP) defaultStream();
+ defaultStream::instance = new(ResourceObj::C_HEAP, mtInternal) defaultStream();
tty = defaultStream::instance;
// We want to ensure that time stamps in GC logs consider time 0
@@ -833,9 +833,9 @@
gclog_or_tty = tty; // default to tty
if (Arguments::gc_log_filename() != NULL) {
fileStream * gclog = UseGCLogFileRotation ?
- new(ResourceObj::C_HEAP)
+ new(ResourceObj::C_HEAP, mtInternal)
rotatingFileStream(Arguments::gc_log_filename()) :
- new(ResourceObj::C_HEAP)
+ new(ResourceObj::C_HEAP, mtInternal)
fileStream(Arguments::gc_log_filename());
if (gclog->is_open()) {
// now we update the time stamp of the GC log to be synced up
@@ -940,7 +940,7 @@
bufferedStream::bufferedStream(size_t initial_size, size_t bufmax) : outputStream() {
buffer_length = initial_size;
- buffer = NEW_C_HEAP_ARRAY(char, buffer_length);
+ buffer = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal);
buffer_pos = 0;
buffer_fixed = false;
buffer_max = bufmax;
@@ -971,7 +971,7 @@
if (end < buffer_length * 2) {
end = buffer_length * 2;
}
- buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end);
+ buffer = REALLOC_C_HEAP_ARRAY(char, buffer, end, mtInternal);
buffer_length = end;
}
}
@@ -989,7 +989,7 @@
bufferedStream::~bufferedStream() {
if (!buffer_fixed) {
- FREE_C_HEAP_ARRAY(char, buffer);
+ FREE_C_HEAP_ARRAY(char, buffer, mtInternal);
}
}
--- a/hotspot/src/share/vm/utilities/stack.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/stack.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_UTILITIES_STACK_HPP
#define SHARE_VM_UTILITIES_STACK_HPP
+#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
// Class Stack (below) grows and shrinks by linking together "segments" which
@@ -51,11 +52,11 @@
// implementation in class Stack assumes that alloc() will terminate the process
// if the allocation fails.
-template <class E> class StackIterator;
+template <class E, MEMFLAGS F> class StackIterator;
// StackBase holds common data/methods that don't depend on the element type,
// factored out to reduce template code duplication.
-class StackBase
+template <MEMFLAGS F> class StackBase
{
public:
size_t segment_size() const { return _seg_size; } // Elements per segment.
@@ -89,11 +90,11 @@
#define inline
#endif // __GNUC__
-template <class E>
-class Stack: public StackBase
+template <class E, MEMFLAGS F>
+class Stack: public StackBase<F>
{
public:
- friend class StackIterator<E>;
+ friend class StackIterator<E, F>;
// segment_size: number of items per segment
// max_cache_size: maxmium number of *segments* to cache
@@ -103,15 +104,15 @@
size_t max_cache_size = 4, size_t max_size = 0);
inline ~Stack() { clear(true); }
- inline bool is_empty() const { return _cur_seg == NULL; }
- inline bool is_full() const { return _full_seg_size >= max_size(); }
+ inline bool is_empty() const { return this->_cur_seg == NULL; }
+ inline bool is_full() const { return this->_full_seg_size >= this->max_size(); }
// Performance sensitive code should use is_empty() instead of size() == 0 and
// is_full() instead of size() == max_size(). Using a conditional here allows
// just one var to be updated when pushing/popping elements instead of two;
// _full_seg_size is updated only when pushing/popping segments.
inline size_t size() const {
- return is_empty() ? 0 : _full_seg_size + _cur_seg_size;
+ return is_empty() ? 0 : this->_full_seg_size + this->_cur_seg_size;
}
inline void push(E elem);
@@ -161,18 +162,18 @@
E* _cache; // Segment cache to avoid ping-ponging.
};
-template <class E> class ResourceStack: public Stack<E>, public ResourceObj
+template <class E, MEMFLAGS F> class ResourceStack: public Stack<E, F>, public ResourceObj
{
public:
// If this class becomes widely used, it may make sense to save the Thread
// and use it when allocating segments.
- ResourceStack(size_t segment_size = Stack<E>::default_segment_size()):
- Stack<E>(segment_size, max_uintx)
+// ResourceStack(size_t segment_size = Stack<E, F>::default_segment_size()):
+ ResourceStack(size_t segment_size): Stack<E, F>(segment_size, max_uintx)
{ }
// Set the segment pointers to NULL so the parent dtor does not free them;
// that must be done by the ResourceMark code.
- ~ResourceStack() { Stack<E>::reset(true); }
+ ~ResourceStack() { Stack<E, F>::reset(true); }
protected:
virtual E* alloc(size_t bytes);
@@ -182,13 +183,13 @@
void clear(bool clear_cache = false);
};
-template <class E>
+template <class E, MEMFLAGS F>
class StackIterator: public StackObj
{
public:
- StackIterator(Stack<E>& stack): _stack(stack) { sync(); }
+ StackIterator(Stack<E, F>& stack): _stack(stack) { sync(); }
- Stack<E>& stack() const { return _stack; }
+ Stack<E, F>& stack() const { return _stack; }
bool is_empty() const { return _cur_seg == NULL; }
@@ -198,7 +199,7 @@
void sync(); // Sync the iterator's state to the stack's current state.
private:
- Stack<E>& _stack;
+ Stack<E, F>& _stack;
size_t _cur_seg_size;
E* _cur_seg;
size_t _full_seg_size;
--- a/hotspot/src/share/vm/utilities/stack.inline.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/stack.inline.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -27,7 +27,7 @@
#include "utilities/stack.hpp"
-StackBase::StackBase(size_t segment_size, size_t max_cache_size,
+template <MEMFLAGS F> StackBase<F>::StackBase(size_t segment_size, size_t max_cache_size,
size_t max_size):
_seg_size(segment_size),
_max_cache_size(max_cache_size),
@@ -36,7 +36,7 @@
assert(_max_size % _seg_size == 0, "not a multiple");
}
-size_t StackBase::adjust_max_size(size_t max_size, size_t seg_size)
+template <MEMFLAGS F> size_t StackBase<F>::adjust_max_size(size_t max_size, size_t seg_size)
{
assert(seg_size > 0, "cannot be 0");
assert(max_size >= seg_size || max_size == 0, "max_size too small");
@@ -47,54 +47,54 @@
return (max_size + seg_size - 1) / seg_size * seg_size;
}
-template <class E>
-Stack<E>::Stack(size_t segment_size, size_t max_cache_size, size_t max_size):
- StackBase(adjust_segment_size(segment_size), max_cache_size, max_size)
+template <class E, MEMFLAGS F>
+Stack<E, F>::Stack(size_t segment_size, size_t max_cache_size, size_t max_size):
+ StackBase<F>(adjust_segment_size(segment_size), max_cache_size, max_size)
{
reset(true);
}
-template <class E>
-void Stack<E>::push(E item)
+template <class E, MEMFLAGS F>
+void Stack<E, F>::push(E item)
{
assert(!is_full(), "pushing onto a full stack");
- if (_cur_seg_size == _seg_size) {
+ if (this->_cur_seg_size == this->_seg_size) {
push_segment();
}
- _cur_seg[_cur_seg_size] = item;
- ++_cur_seg_size;
+ this->_cur_seg[this->_cur_seg_size] = item;
+ ++this->_cur_seg_size;
}
-template <class E>
-E Stack<E>::pop()
+template <class E, MEMFLAGS F>
+E Stack<E, F>::pop()
{
assert(!is_empty(), "popping from an empty stack");
- if (_cur_seg_size == 1) {
- E tmp = _cur_seg[--_cur_seg_size];
+ if (this->_cur_seg_size == 1) {
+ E tmp = _cur_seg[--this->_cur_seg_size];
pop_segment();
return tmp;
}
- return _cur_seg[--_cur_seg_size];
+ return this->_cur_seg[--this->_cur_seg_size];
}
-template <class E>
-void Stack<E>::clear(bool clear_cache)
+template <class E, MEMFLAGS F>
+void Stack<E, F>::clear(bool clear_cache)
{
free_segments(_cur_seg);
if (clear_cache) free_segments(_cache);
reset(clear_cache);
}
-template <class E>
-size_t Stack<E>::default_segment_size()
+template <class E, MEMFLAGS F>
+size_t Stack<E, F>::default_segment_size()
{
// Number of elements that fit in 4K bytes minus the size of two pointers
// (link field and malloc header).
return (4096 - 2 * sizeof(E*)) / sizeof(E);
}
-template <class E>
-size_t Stack<E>::adjust_segment_size(size_t seg_size)
+template <class E, MEMFLAGS F>
+size_t Stack<E, F>::adjust_segment_size(size_t seg_size)
{
const size_t elem_sz = sizeof(E);
const size_t ptr_sz = sizeof(E*);
@@ -105,93 +105,93 @@
return seg_size;
}
-template <class E>
-size_t Stack<E>::link_offset() const
+template <class E, MEMFLAGS F>
+size_t Stack<E, F>::link_offset() const
{
- return align_size_up(_seg_size * sizeof(E), sizeof(E*));
+ return align_size_up(this->_seg_size * sizeof(E), sizeof(E*));
}
-template <class E>
-size_t Stack<E>::segment_bytes() const
+template <class E, MEMFLAGS F>
+size_t Stack<E, F>::segment_bytes() const
{
return link_offset() + sizeof(E*);
}
-template <class E>
-E** Stack<E>::link_addr(E* seg) const
+template <class E, MEMFLAGS F>
+E** Stack<E, F>::link_addr(E* seg) const
{
return (E**) ((char*)seg + link_offset());
}
-template <class E>
-E* Stack<E>::get_link(E* seg) const
+template <class E, MEMFLAGS F>
+E* Stack<E, F>::get_link(E* seg) const
{
return *link_addr(seg);
}
-template <class E>
-E* Stack<E>::set_link(E* new_seg, E* old_seg)
+template <class E, MEMFLAGS F>
+E* Stack<E, F>::set_link(E* new_seg, E* old_seg)
{
*link_addr(new_seg) = old_seg;
return new_seg;
}
-template <class E>
-E* Stack<E>::alloc(size_t bytes)
+template <class E, MEMFLAGS F>
+E* Stack<E, F>::alloc(size_t bytes)
{
- return (E*) NEW_C_HEAP_ARRAY(char, bytes);
+ return (E*) NEW_C_HEAP_ARRAY(char, bytes, F);
}
-template <class E>
-void Stack<E>::free(E* addr, size_t bytes)
+template <class E, MEMFLAGS F>
+void Stack<E, F>::free(E* addr, size_t bytes)
{
- FREE_C_HEAP_ARRAY(char, (char*) addr);
+ FREE_C_HEAP_ARRAY(char, (char*) addr, F);
}
-template <class E>
-void Stack<E>::push_segment()
+template <class E, MEMFLAGS F>
+void Stack<E, F>::push_segment()
{
- assert(_cur_seg_size == _seg_size, "current segment is not full");
+ assert(this->_cur_seg_size == this->_seg_size, "current segment is not full");
E* next;
- if (_cache_size > 0) {
+ if (this->_cache_size > 0) {
// Use a cached segment.
next = _cache;
_cache = get_link(_cache);
- --_cache_size;
+ --this->_cache_size;
} else {
next = alloc(segment_bytes());
DEBUG_ONLY(zap_segment(next, true);)
}
const bool at_empty_transition = is_empty();
- _cur_seg = set_link(next, _cur_seg);
- _cur_seg_size = 0;
- _full_seg_size += at_empty_transition ? 0 : _seg_size;
+ this->_cur_seg = set_link(next, _cur_seg);
+ this->_cur_seg_size = 0;
+ this->_full_seg_size += at_empty_transition ? 0 : this->_seg_size;
DEBUG_ONLY(verify(at_empty_transition);)
}
-template <class E>
-void Stack<E>::pop_segment()
+template <class E, MEMFLAGS F>
+void Stack<E, F>::pop_segment()
{
- assert(_cur_seg_size == 0, "current segment is not empty");
+ assert(this->_cur_seg_size == 0, "current segment is not empty");
E* const prev = get_link(_cur_seg);
- if (_cache_size < _max_cache_size) {
+ if (this->_cache_size < this->_max_cache_size) {
// Add the current segment to the cache.
DEBUG_ONLY(zap_segment(_cur_seg, false);)
_cache = set_link(_cur_seg, _cache);
- ++_cache_size;
+ ++this->_cache_size;
} else {
DEBUG_ONLY(zap_segment(_cur_seg, true);)
free(_cur_seg, segment_bytes());
}
const bool at_empty_transition = prev == NULL;
- _cur_seg = prev;
- _cur_seg_size = _seg_size;
- _full_seg_size -= at_empty_transition ? 0 : _seg_size;
+ this->_cur_seg = prev;
+ this->_cur_seg_size = this->_seg_size;
+ this->_full_seg_size -= at_empty_transition ? 0 : this->_seg_size;
DEBUG_ONLY(verify(at_empty_transition);)
}
-template <class E>
-void Stack<E>::free_segments(E* seg)
+template <class E, MEMFLAGS F>
+void Stack<E, F>::free_segments(E* seg)
{
const size_t bytes = segment_bytes();
while (seg != NULL) {
@@ -201,37 +201,37 @@
}
}
-template <class E>
-void Stack<E>::reset(bool reset_cache)
+template <class E, MEMFLAGS F>
+void Stack<E, F>::reset(bool reset_cache)
{
- _cur_seg_size = _seg_size; // So push() will alloc a new segment.
- _full_seg_size = 0;
+ this->_cur_seg_size = this->_seg_size; // So push() will alloc a new segment.
+ this->_full_seg_size = 0;
_cur_seg = NULL;
if (reset_cache) {
- _cache_size = 0;
+ this->_cache_size = 0;
_cache = NULL;
}
}
#ifdef ASSERT
-template <class E>
-void Stack<E>::verify(bool at_empty_transition) const
+template <class E, MEMFLAGS F>
+void Stack<E, F>::verify(bool at_empty_transition) const
{
- assert(size() <= max_size(), "stack exceeded bounds");
- assert(cache_size() <= max_cache_size(), "cache exceeded bounds");
- assert(_cur_seg_size <= segment_size(), "segment index exceeded bounds");
+ assert(size() <= this->max_size(), "stack exceeded bounds");
+ assert(this->cache_size() <= this->max_cache_size(), "cache exceeded bounds");
+ assert(this->_cur_seg_size <= this->segment_size(), "segment index exceeded bounds");
- assert(_full_seg_size % _seg_size == 0, "not a multiple");
+ assert(this->_full_seg_size % this->_seg_size == 0, "not a multiple");
assert(at_empty_transition || is_empty() == (size() == 0), "mismatch");
- assert((_cache == NULL) == (cache_size() == 0), "mismatch");
+ assert((_cache == NULL) == (this->cache_size() == 0), "mismatch");
if (is_empty()) {
- assert(_cur_seg_size == segment_size(), "sanity");
+ assert(this->_cur_seg_size == this->segment_size(), "sanity");
}
}
-template <class E>
-void Stack<E>::zap_segment(E* seg, bool zap_link_field) const
+template <class E, MEMFLAGS F>
+void Stack<E, F>::zap_segment(E* seg, bool zap_link_field) const
{
if (!ZapStackSegments) return;
const size_t zap_bytes = segment_bytes() - (zap_link_field ? 0 : sizeof(E*));
@@ -243,28 +243,28 @@
}
#endif
-template <class E>
-E* ResourceStack<E>::alloc(size_t bytes)
+template <class E, MEMFLAGS F>
+E* ResourceStack<E, F>::alloc(size_t bytes)
{
return (E*) resource_allocate_bytes(bytes);
}
-template <class E>
-void ResourceStack<E>::free(E* addr, size_t bytes)
+template <class E, MEMFLAGS F>
+void ResourceStack<E, F>::free(E* addr, size_t bytes)
{
resource_free_bytes((char*) addr, bytes);
}
-template <class E>
-void StackIterator<E>::sync()
+template <class E, MEMFLAGS F>
+void StackIterator<E, F>::sync()
{
_full_seg_size = _stack._full_seg_size;
_cur_seg_size = _stack._cur_seg_size;
_cur_seg = _stack._cur_seg;
}
-template <class E>
-E* StackIterator<E>::next_addr()
+template <class E, MEMFLAGS F>
+E* StackIterator<E, F>::next_addr()
{
assert(!is_empty(), "no items left");
if (_cur_seg_size == 1) {
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -132,8 +132,8 @@
}
#endif // TASKQUEUE_STATS
-template <unsigned int N>
-class TaskQueueSuper: public CHeapObj {
+template <unsigned int N, MEMFLAGS F>
+class TaskQueueSuper: public CHeapObj<F> {
protected:
// Internal type for indexing the queue; also used for the tag.
typedef NOT_LP64(uint16_t) LP64_ONLY(uint32_t) idx_t;
@@ -249,22 +249,27 @@
TASKQUEUE_STATS_ONLY(TaskQueueStats stats;)
};
-template<class E, unsigned int N = TASKQUEUE_SIZE>
-class GenericTaskQueue: public TaskQueueSuper<N> {
-protected:
- typedef typename TaskQueueSuper<N>::Age Age;
- typedef typename TaskQueueSuper<N>::idx_t idx_t;
+
- using TaskQueueSuper<N>::_bottom;
- using TaskQueueSuper<N>::_age;
- using TaskQueueSuper<N>::increment_index;
- using TaskQueueSuper<N>::decrement_index;
- using TaskQueueSuper<N>::dirty_size;
+template <class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
+class GenericTaskQueue: public TaskQueueSuper<N, F> {
+protected:
+ typedef typename TaskQueueSuper<N, F>::Age Age;
+ typedef typename TaskQueueSuper<N, F>::idx_t idx_t;
+
+ using TaskQueueSuper<N, F>::_bottom;
+ using TaskQueueSuper<N, F>::_age;
+ using TaskQueueSuper<N, F>::increment_index;
+ using TaskQueueSuper<N, F>::decrement_index;
+ using TaskQueueSuper<N, F>::dirty_size;
public:
- using TaskQueueSuper<N>::max_elems;
- using TaskQueueSuper<N>::size;
- TASKQUEUE_STATS_ONLY(using TaskQueueSuper<N>::stats;)
+ using TaskQueueSuper<N, F>::max_elems;
+ using TaskQueueSuper<N, F>::size;
+
+#if TASKQUEUE_STATS
+ using TaskQueueSuper<N, F>::stats;
+#endif
private:
// Slow paths for push, pop_local. (pop_global has no fast path.)
@@ -302,18 +307,18 @@
volatile E* _elems;
};
-template<class E, unsigned int N>
-GenericTaskQueue<E, N>::GenericTaskQueue() {
+template<class E, MEMFLAGS F, unsigned int N>
+GenericTaskQueue<E, F, N>::GenericTaskQueue() {
assert(sizeof(Age) == sizeof(size_t), "Depends on this.");
}
-template<class E, unsigned int N>
-void GenericTaskQueue<E, N>::initialize() {
- _elems = NEW_C_HEAP_ARRAY(E, N);
+template<class E, MEMFLAGS F, unsigned int N>
+void GenericTaskQueue<E, F, N>::initialize() {
+ _elems = NEW_C_HEAP_ARRAY(E, N, F);
}
-template<class E, unsigned int N>
-void GenericTaskQueue<E, N>::oops_do(OopClosure* f) {
+template<class E, MEMFLAGS F, unsigned int N>
+void GenericTaskQueue<E, F, N>::oops_do(OopClosure* f) {
// tty->print_cr("START OopTaskQueue::oops_do");
uint iters = size();
uint index = _bottom;
@@ -329,8 +334,8 @@
// tty->print_cr("END OopTaskQueue::oops_do");
}
-template<class E, unsigned int N>
-bool GenericTaskQueue<E, N>::push_slow(E t, uint dirty_n_elems) {
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::push_slow(E t, uint dirty_n_elems) {
if (dirty_n_elems == N - 1) {
// Actually means 0, so do the push.
uint localBot = _bottom;
@@ -349,8 +354,8 @@
// whenever the queue goes empty which it will do here if this thread
// gets the last task or in pop_global() if the queue wraps (top == 0
// and pop_global() succeeds, see pop_global()).
-template<class E, unsigned int N>
-bool GenericTaskQueue<E, N>::pop_local_slow(uint localBot, Age oldAge) {
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_local_slow(uint localBot, Age oldAge) {
// This queue was observed to contain exactly one element; either this
// thread will claim it, or a competing "pop_global". In either case,
// the queue will be logically empty afterwards. Create a new Age value
@@ -382,8 +387,8 @@
return false;
}
-template<class E, unsigned int N>
-bool GenericTaskQueue<E, N>::pop_global(E& t) {
+template<class E, MEMFLAGS F, unsigned int N>
+bool GenericTaskQueue<E, F, N>::pop_global(E& t) {
Age oldAge = _age.get();
uint localBot = _bottom;
uint n_elems = size(localBot, oldAge.top());
@@ -402,9 +407,9 @@
return resAge == oldAge;
}
-template<class E, unsigned int N>
-GenericTaskQueue<E, N>::~GenericTaskQueue() {
- FREE_C_HEAP_ARRAY(E, _elems);
+template<class E, MEMFLAGS F, unsigned int N>
+GenericTaskQueue<E, F, N>::~GenericTaskQueue() {
+ FREE_C_HEAP_ARRAY(E, _elems, F);
}
// OverflowTaskQueue is a TaskQueue that also includes an overflow stack for
@@ -418,12 +423,12 @@
// Note that size() is not hidden--it returns the number of elements in the
// TaskQueue, and does not include the size of the overflow stack. This
// simplifies replacement of GenericTaskQueues with OverflowTaskQueues.
-template<class E, unsigned int N = TASKQUEUE_SIZE>
-class OverflowTaskQueue: public GenericTaskQueue<E, N>
+template<class E, MEMFLAGS F, unsigned int N = TASKQUEUE_SIZE>
+class OverflowTaskQueue: public GenericTaskQueue<E, F, N>
{
public:
- typedef Stack<E> overflow_t;
- typedef GenericTaskQueue<E, N> taskqueue_t;
+ typedef Stack<E, F> overflow_t;
+ typedef GenericTaskQueue<E, F, N> taskqueue_t;
TASKQUEUE_STATS_ONLY(using taskqueue_t::stats;)
@@ -445,8 +450,8 @@
overflow_t _overflow_stack;
};
-template <class E, unsigned int N>
-bool OverflowTaskQueue<E, N>::push(E t)
+template <class E, MEMFLAGS F, unsigned int N>
+bool OverflowTaskQueue<E, F, N>::push(E t)
{
if (!taskqueue_t::push(t)) {
overflow_stack()->push(t);
@@ -455,15 +460,15 @@
return true;
}
-template <class E, unsigned int N>
-bool OverflowTaskQueue<E, N>::pop_overflow(E& t)
+template <class E, MEMFLAGS F, unsigned int N>
+bool OverflowTaskQueue<E, F, N>::pop_overflow(E& t)
{
if (overflow_empty()) return false;
t = overflow_stack()->pop();
return true;
}
-class TaskQueueSetSuper: public CHeapObj {
+class TaskQueueSetSuper {
protected:
static int randomParkAndMiller(int* seed0);
public:
@@ -471,8 +476,11 @@
virtual bool peek() = 0;
};
-template<class T>
-class GenericTaskQueueSet: public TaskQueueSetSuper {
+template <MEMFLAGS F> class TaskQueueSetSuperImpl: public CHeapObj<F>, public TaskQueueSetSuper {
+};
+
+template<class T, MEMFLAGS F>
+class GenericTaskQueueSet: public TaskQueueSetSuperImpl<F> {
private:
uint _n;
T** _queues;
@@ -482,7 +490,7 @@
GenericTaskQueueSet(int n) : _n(n) {
typedef T* GenericTaskQueuePtr;
- _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n);
+ _queues = NEW_C_HEAP_ARRAY(GenericTaskQueuePtr, n, F);
for (int i = 0; i < n; i++) {
_queues[i] = NULL;
}
@@ -506,19 +514,19 @@
bool peek();
};
-template<class T> void
-GenericTaskQueueSet<T>::register_queue(uint i, T* q) {
+template<class T, MEMFLAGS F> void
+GenericTaskQueueSet<T, F>::register_queue(uint i, T* q) {
assert(i < _n, "index out of range.");
_queues[i] = q;
}
-template<class T> T*
-GenericTaskQueueSet<T>::queue(uint i) {
+template<class T, MEMFLAGS F> T*
+GenericTaskQueueSet<T, F>::queue(uint i) {
return _queues[i];
}
-template<class T> bool
-GenericTaskQueueSet<T>::steal(uint queue_num, int* seed, E& t) {
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal(uint queue_num, int* seed, E& t) {
for (uint i = 0; i < 2 * _n; i++) {
if (steal_best_of_2(queue_num, seed, t)) {
TASKQUEUE_STATS_ONLY(queue(queue_num)->stats.record_steal(true));
@@ -529,8 +537,8 @@
return false;
}
-template<class T> bool
-GenericTaskQueueSet<T>::steal_best_of_all(uint queue_num, int* seed, E& t) {
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal_best_of_all(uint queue_num, int* seed, E& t) {
if (_n > 2) {
int best_k;
uint best_sz = 0;
@@ -553,11 +561,11 @@
}
}
-template<class T> bool
-GenericTaskQueueSet<T>::steal_1_random(uint queue_num, int* seed, E& t) {
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal_1_random(uint queue_num, int* seed, E& t) {
if (_n > 2) {
uint k = queue_num;
- while (k == queue_num) k = randomParkAndMiller(seed) % _n;
+ while (k == queue_num) k = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
return _queues[2]->pop_global(t);
} else if (_n == 2) {
// Just try the other one.
@@ -569,13 +577,13 @@
}
}
-template<class T> bool
-GenericTaskQueueSet<T>::steal_best_of_2(uint queue_num, int* seed, E& t) {
+template<class T, MEMFLAGS F> bool
+GenericTaskQueueSet<T, F>::steal_best_of_2(uint queue_num, int* seed, E& t) {
if (_n > 2) {
uint k1 = queue_num;
- while (k1 == queue_num) k1 = randomParkAndMiller(seed) % _n;
+ while (k1 == queue_num) k1 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
uint k2 = queue_num;
- while (k2 == queue_num || k2 == k1) k2 = randomParkAndMiller(seed) % _n;
+ while (k2 == queue_num || k2 == k1) k2 = TaskQueueSetSuper::randomParkAndMiller(seed) % _n;
// Sample both and try the larger.
uint sz1 = _queues[k1]->size();
uint sz2 = _queues[k2]->size();
@@ -591,8 +599,8 @@
}
}
-template<class T>
-bool GenericTaskQueueSet<T>::peek() {
+template<class T, MEMFLAGS F>
+bool GenericTaskQueueSet<T, F>::peek() {
// Try all the queues.
for (uint j = 0; j < _n; j++) {
if (_queues[j]->peek())
@@ -602,7 +610,7 @@
}
// When to terminate from the termination protocol.
-class TerminatorTerminator: public CHeapObj {
+class TerminatorTerminator: public CHeapObj<mtInternal> {
public:
virtual bool should_exit_termination() = 0;
};
@@ -665,8 +673,8 @@
#endif
};
-template<class E, unsigned int N> inline bool
-GenericTaskQueue<E, N>::push(E t) {
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::push(E t) {
uint localBot = _bottom;
assert((localBot >= 0) && (localBot < N), "_bottom out of range.");
idx_t top = _age.top();
@@ -683,8 +691,8 @@
}
}
-template<class E, unsigned int N> inline bool
-GenericTaskQueue<E, N>::pop_local(E& t) {
+template<class E, MEMFLAGS F, unsigned int N> inline bool
+GenericTaskQueue<E, F, N>::pop_local(E& t) {
uint localBot = _bottom;
// This value cannot be N-1. That can only occur as a result of
// the assignment to bottom in this method. If it does, this method
@@ -715,8 +723,8 @@
}
}
-typedef GenericTaskQueue<oop> OopTaskQueue;
-typedef GenericTaskQueueSet<OopTaskQueue> OopTaskQueueSet;
+typedef GenericTaskQueue<oop, mtGC> OopTaskQueue;
+typedef GenericTaskQueueSet<OopTaskQueue, mtGC> OopTaskQueueSet;
#ifdef _MSC_VER
#pragma warning(push)
@@ -796,11 +804,11 @@
#pragma warning(pop)
#endif
-typedef OverflowTaskQueue<StarTask> OopStarTaskQueue;
-typedef GenericTaskQueueSet<OopStarTaskQueue> OopStarTaskQueueSet;
+typedef OverflowTaskQueue<StarTask, mtClass> OopStarTaskQueue;
+typedef GenericTaskQueueSet<OopStarTaskQueue, mtClass> OopStarTaskQueueSet;
-typedef OverflowTaskQueue<size_t> RegionTaskQueue;
-typedef GenericTaskQueueSet<RegionTaskQueue> RegionTaskQueueSet;
+typedef OverflowTaskQueue<size_t, mtInternal> RegionTaskQueue;
+typedef GenericTaskQueueSet<RegionTaskQueue, mtClass> RegionTaskQueueSet;
#endif // SHARE_VM_UTILITIES_TASKQUEUE_HPP
--- a/hotspot/src/share/vm/utilities/vmError.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/vmError.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -33,6 +33,7 @@
#include "runtime/thread.hpp"
#include "runtime/vmThread.hpp"
#include "runtime/vm_operations.hpp"
+#include "services/memTracker.hpp"
#include "utilities/debug.hpp"
#include "utilities/decoder.hpp"
#include "utilities/defaultStream.hpp"
@@ -820,6 +821,9 @@
static bool transmit_report_done = false; // done error reporting
static fdStream log; // error log
+ // disble NMT to avoid further exception
+ MemTracker::shutdown(MemTracker::NMT_error_reporting);
+
if (SuppressFatalErrorMessage) {
os::abort();
}
--- a/hotspot/src/share/vm/utilities/workgroup.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/workgroup.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -77,7 +77,7 @@
name(),
total_workers());
}
- _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, total_workers());
+ _gang_workers = NEW_C_HEAP_ARRAY(GangWorker*, total_workers(), mtInternal);
if (gang_workers() == NULL) {
vm_exit_out_of_memory(0, "Cannot create GangWorker array.");
return false;
@@ -241,6 +241,7 @@
void GangWorker::initialize() {
this->initialize_thread_local_storage();
+ this->record_stack_base_and_size();
assert(_gang != NULL, "No gang to run in");
os::set_priority(this, NearMaxPriority);
if (TraceWorkGang) {
@@ -421,7 +422,7 @@
SubTasksDone::SubTasksDone(uint n) :
_n_tasks(n), _n_threads(1), _tasks(NULL) {
- _tasks = NEW_C_HEAP_ARRAY(uint, n);
+ _tasks = NEW_C_HEAP_ARRAY(uint, n, mtInternal);
guarantee(_tasks != NULL, "alloc failure");
clear();
}
@@ -476,7 +477,7 @@
SubTasksDone::~SubTasksDone() {
- if (_tasks != NULL) FREE_C_HEAP_ARRAY(jint, _tasks);
+ if (_tasks != NULL) FREE_C_HEAP_ARRAY(jint, _tasks, mtInternal);
}
// *** SequentialSubTasksDone
--- a/hotspot/src/share/vm/utilities/workgroup.hpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/workgroup.hpp Wed Jul 05 18:16:35 2017 +0200
@@ -123,7 +123,7 @@
// Class AbstractWorkGang:
// An abstract class representing a gang of workers.
// You subclass this to supply an implementation of run_task().
-class AbstractWorkGang: public CHeapObj {
+class AbstractWorkGang: public CHeapObj<mtInternal> {
// Here's the public interface to this class.
public:
// Constructor and destructor.
@@ -402,7 +402,7 @@
// subtasks will be identified by integer indices, usually elements of an
// enumeration type.
-class SubTasksDone : public CHeapObj {
+class SubTasksDone: public CHeapObj<mtInternal> {
uint* _tasks;
uint _n_tasks;
// _n_threads is used to determine when a sub task is done.
--- a/hotspot/src/share/vm/utilities/xmlstream.cpp Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/src/share/vm/utilities/xmlstream.cpp Wed Jul 05 18:16:35 2017 +0200
@@ -43,7 +43,7 @@
#ifdef ASSERT
_element_depth = 0;
int init_len = 100;
- char* init_buf = NEW_C_HEAP_ARRAY(char, init_len);
+ char* init_buf = NEW_C_HEAP_ARRAY(char, init_len, mtInternal);
_element_close_stack_low = init_buf;
_element_close_stack_high = init_buf + init_len;
_element_close_stack_ptr = init_buf + init_len - 1;
@@ -58,7 +58,7 @@
#ifdef ASSERT
xmlStream::~xmlStream() {
- FREE_C_HEAP_ARRAY(char, _element_close_stack_low);
+ FREE_C_HEAP_ARRAY(char, _element_close_stack_low, mtInternal);
}
#endif
@@ -155,14 +155,14 @@
int old_len = _element_close_stack_high - old_ptr;
int new_len = old_len * 2;
if (new_len < 100) new_len = 100;
- char* new_low = NEW_C_HEAP_ARRAY(char, new_len);
+ char* new_low = NEW_C_HEAP_ARRAY(char, new_len, mtInternal);
char* new_high = new_low + new_len;
char* new_ptr = new_high - old_len;
memcpy(new_ptr, old_ptr, old_len);
_element_close_stack_high = new_high;
_element_close_stack_low = new_low;
_element_close_stack_ptr = new_ptr;
- FREE_C_HEAP_ARRAY(char, old_low);
+ FREE_C_HEAP_ARRAY(char, old_low, mtInternal);
push_ptr = new_ptr - (tag_len+1);
}
assert(push_ptr >= _element_close_stack_low, "in range");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/7177917/Test7177917.java Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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.
+ *
+ */
+
+/*
+ * Micro-benchmark for Math.pow() and Math.exp()
+ */
+
+import java.util.*;
+
+public class Test7177917 {
+
+ static double d;
+
+ static Random r = new Random(0);
+
+ static long m_pow(double[][] values) {
+ double res = 0;
+ long start = System.nanoTime();
+ for (int i = 0; i < values.length; i++) {
+ res += Math.pow(values[i][0], values[i][1]);
+ }
+ long stop = System.nanoTime();
+ d = res;
+ return (stop - start) / 1000;
+ }
+
+ static long m_exp(double[] values) {
+ double res = 0;
+ long start = System.nanoTime();
+ for (int i = 0; i < values.length; i++) {
+ res += Math.exp(values[i]);
+ }
+ long stop = System.nanoTime();
+ d = res;
+ return (stop - start) / 1000;
+ }
+
+ static double[][] pow_values(int nb) {
+ double[][] res = new double[nb][2];
+ for (int i = 0; i < nb; i++) {
+ double ylogx = (1 + (r.nextDouble() * 2045)) - 1023; // 2045 rather than 2046 as a safety margin
+ double x = Math.abs(Double.longBitsToDouble(r.nextLong()));
+ while (x != x) {
+ x = Math.abs(Double.longBitsToDouble(r.nextLong()));
+ }
+ double logx = Math.log(x) / Math.log(2);
+ double y = ylogx / logx;
+
+ res[i][0] = x;
+ res[i][1] = y;
+ }
+ return res;
+ }
+
+ static double[] exp_values(int nb) {
+ double[] res = new double[nb];
+ for (int i = 0; i < nb; i++) {
+ double ylogx = (1 + (r.nextDouble() * 2045)) - 1023; // 2045 rather than 2046 as a safety margin
+ double x = Math.E;
+ double logx = Math.log(x) / Math.log(2);
+ double y = ylogx / logx;
+ res[i] = y;
+ }
+ return res;
+ }
+
+ static public void main(String[] args) {
+ {
+ // warmup
+ double[][] warmup_values = pow_values(10);
+ m_pow(warmup_values);
+
+ for (int i = 0; i < 20000; i++) {
+ m_pow(warmup_values);
+ }
+ // test pow perf
+ double[][] values = pow_values(1000000);
+ System.out.println("==> POW " + m_pow(values));
+
+ // force uncommon trap
+ double[][] nan_values = new double[1][2];
+ nan_values[0][0] = Double.NaN;
+ nan_values[0][1] = Double.NaN;
+ m_pow(nan_values);
+
+ // force recompilation
+ for (int i = 0; i < 20000; i++) {
+ m_pow(warmup_values);
+ }
+
+ // test pow perf again
+ System.out.println("==> POW " + m_pow(values));
+ }
+ {
+ // warmup
+ double[] warmup_values = exp_values(10);
+ m_exp(warmup_values);
+
+ for (int i = 0; i < 20000; i++) {
+ m_exp(warmup_values);
+ }
+
+ // test pow perf
+ double[] values = exp_values(1000000);
+ System.out.println("==> EXP " + m_exp(values));
+
+ // force uncommon trap
+ double[] nan_values = new double[1];
+ nan_values[0] = Double.NaN;
+ m_exp(nan_values);
+
+ // force recompilation
+ for (int i = 0; i < 20000; i++) {
+ m_exp(warmup_values);
+ }
+
+ // test pow perf again
+ System.out.println("==> EXP " + m_exp(values));
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/6294277/SourceDebugExtension.java Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,135 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * 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 6294277
+ * @summary java -Xdebug crashes on SourceDebugExtension attribute larger than 64K
+ */
+import java.io.*;
+
+public class SourceDebugExtension extends ClassLoader
+{
+ static final int attrSize = 68000;
+ static byte[] header = {
+(byte)0xca, (byte)0xfe, (byte)0xba, (byte)0xbe, (byte)0x00, (byte)0x00, (byte)0x00,
+(byte)0x32, (byte)0x00, (byte)0x1e, (byte)0x0a, (byte)0x00, (byte)0x06, (byte)0x00,
+(byte)0x0f, (byte)0x09, (byte)0x00, (byte)0x10, (byte)0x00, (byte)0x11, (byte)0x08,
+(byte)0x00, (byte)0x12, (byte)0x0a, (byte)0x00, (byte)0x13, (byte)0x00, (byte)0x14,
+(byte)0x07, (byte)0x00, (byte)0x15, (byte)0x07, (byte)0x00, (byte)0x16, (byte)0x01,
+(byte)0x00, (byte)0x06, (byte)0x3c, (byte)0x69, (byte)0x6e, (byte)0x69, (byte)0x74,
+(byte)0x3e, (byte)0x01, (byte)0x00, (byte)0x03, (byte)0x28, (byte)0x29, (byte)0x56,
+(byte)0x01, (byte)0x00, (byte)0x04, (byte)0x43, (byte)0x6f, (byte)0x64, (byte)0x65,
+(byte)0x01, (byte)0x00, (byte)0x0f, (byte)0x4c, (byte)0x69, (byte)0x6e, (byte)0x65,
+(byte)0x4e, (byte)0x75, (byte)0x6d, (byte)0x62, (byte)0x65, (byte)0x72, (byte)0x54,
+(byte)0x61, (byte)0x62, (byte)0x6c, (byte)0x65, (byte)0x01, (byte)0x00, (byte)0x04,
+(byte)0x6d, (byte)0x61, (byte)0x69, (byte)0x6e, (byte)0x01, (byte)0x00, (byte)0x16,
+(byte)0x28, (byte)0x5b, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61,
+(byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x53,
+(byte)0x74, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67, (byte)0x3b, (byte)0x29,
+(byte)0x56, (byte)0x01, (byte)0x00, (byte)0x0a, (byte)0x53, (byte)0x6f, (byte)0x75,
+(byte)0x72, (byte)0x63, (byte)0x65, (byte)0x46, (byte)0x69, (byte)0x6c, (byte)0x65,
+(byte)0x01, (byte)0x00, (byte)0x0d, (byte)0x54, (byte)0x65, (byte)0x73, (byte)0x74,
+(byte)0x50, (byte)0x72, (byte)0x6f, (byte)0x67, (byte)0x2e, (byte)0x6a, (byte)0x61,
+(byte)0x76, (byte)0x61, (byte)0x0c, (byte)0x00, (byte)0x07, (byte)0x00, (byte)0x08,
+(byte)0x07, (byte)0x00, (byte)0x17, (byte)0x0c, (byte)0x00, (byte)0x18, (byte)0x00,
+(byte)0x19, (byte)0x01, (byte)0x00, (byte)0x34, (byte)0x54, (byte)0x65, (byte)0x73,
+(byte)0x74, (byte)0x20, (byte)0x70, (byte)0x72, (byte)0x6f, (byte)0x67, (byte)0x72,
+(byte)0x61, (byte)0x6d, (byte)0x20, (byte)0x66, (byte)0x6f, (byte)0x72, (byte)0x20,
+(byte)0x62, (byte)0x69, (byte)0x67, (byte)0x20, (byte)0x53, (byte)0x6f, (byte)0x75,
+(byte)0x72, (byte)0x63, (byte)0x65, (byte)0x44, (byte)0x65, (byte)0x62, (byte)0x75,
+(byte)0x67, (byte)0x45, (byte)0x78, (byte)0x74, (byte)0x65, (byte)0x6e, (byte)0x73,
+(byte)0x69, (byte)0x6f, (byte)0x6e, (byte)0x20, (byte)0x61, (byte)0x74, (byte)0x74,
+(byte)0x72, (byte)0x69, (byte)0x62, (byte)0x75, (byte)0x74, (byte)0x65, (byte)0x73,
+(byte)0x07, (byte)0x00, (byte)0x1a, (byte)0x0c, (byte)0x00, (byte)0x1b, (byte)0x00,
+(byte)0x1c, (byte)0x01, (byte)0x00, (byte)0x08, (byte)0x54, (byte)0x65, (byte)0x73,
+(byte)0x74, (byte)0x50, (byte)0x72, (byte)0x6f, (byte)0x67, (byte)0x01, (byte)0x00,
+(byte)0x10, (byte)0x6a, (byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c,
+(byte)0x61, (byte)0x6e, (byte)0x67, (byte)0x2f, (byte)0x4f, (byte)0x62, (byte)0x6a,
+(byte)0x65, (byte)0x63, (byte)0x74, (byte)0x01, (byte)0x00, (byte)0x10, (byte)0x6a,
+(byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e,
+(byte)0x67, (byte)0x2f, (byte)0x53, (byte)0x79, (byte)0x73, (byte)0x74, (byte)0x65,
+(byte)0x6d, (byte)0x01, (byte)0x00, (byte)0x03, (byte)0x6f, (byte)0x75, (byte)0x74,
+(byte)0x01, (byte)0x00, (byte)0x15, (byte)0x4c, (byte)0x6a, (byte)0x61, (byte)0x76,
+(byte)0x61, (byte)0x2f, (byte)0x69, (byte)0x6f, (byte)0x2f, (byte)0x50, (byte)0x72,
+(byte)0x69, (byte)0x6e, (byte)0x74, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x65,
+(byte)0x61, (byte)0x6d, (byte)0x3b, (byte)0x01, (byte)0x00, (byte)0x13, (byte)0x6a,
+(byte)0x61, (byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x69, (byte)0x6f, (byte)0x2f,
+(byte)0x50, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x74, (byte)0x53, (byte)0x74,
+(byte)0x72, (byte)0x65, (byte)0x61, (byte)0x6d, (byte)0x01, (byte)0x00, (byte)0x07,
+(byte)0x70, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x74, (byte)0x6c, (byte)0x6e,
+(byte)0x01, (byte)0x00, (byte)0x15, (byte)0x28, (byte)0x4c, (byte)0x6a, (byte)0x61,
+(byte)0x76, (byte)0x61, (byte)0x2f, (byte)0x6c, (byte)0x61, (byte)0x6e, (byte)0x67,
+(byte)0x2f, (byte)0x53, (byte)0x74, (byte)0x72, (byte)0x69, (byte)0x6e, (byte)0x67,
+(byte)0x3b, (byte)0x29, (byte)0x56, (byte)0x01, (byte)0x00, (byte)0x14, (byte)0x53,
+(byte)0x6f, (byte)0x75, (byte)0x72, (byte)0x63, (byte)0x65, (byte)0x44, (byte)0x65,
+(byte)0x62, (byte)0x75, (byte)0x67, (byte)0x45, (byte)0x78, (byte)0x74, (byte)0x65,
+(byte)0x6e, (byte)0x73, (byte)0x69, (byte)0x6f, (byte)0x6e, (byte)0x00, (byte)0x21,
+(byte)0x00, (byte)0x05, (byte)0x00, (byte)0x06, (byte)0x00, (byte)0x00, (byte)0x00,
+(byte)0x00, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x07,
+(byte)0x00, (byte)0x08, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09, (byte)0x00,
+(byte)0x00, (byte)0x00, (byte)0x1d, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x01,
+(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x05, (byte)0x2a, (byte)0xb7, (byte)0x00,
+(byte)0x01, (byte)0xb1, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00,
+(byte)0x0a, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x06, (byte)0x00, (byte)0x01,
+(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09, (byte)0x00,
+(byte)0x0b, (byte)0x00, (byte)0x0c, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x09,
+(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x25, (byte)0x00, (byte)0x02, (byte)0x00,
+(byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x09, (byte)0xb2, (byte)0x00,
+(byte)0x02, (byte)0x12, (byte)0x03, (byte)0xb6, (byte)0x00, (byte)0x04, (byte)0xb1,
+(byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x0a, (byte)0x00,
+(byte)0x00, (byte)0x00, (byte)0x0a, (byte)0x00, (byte)0x02, (byte)0x00, (byte)0x00,
+(byte)0x00, (byte)0x03, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x04, (byte)0x00,
+(byte)0x02, (byte)0x00, (byte)0x0d, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02,
+(byte)0x00, (byte)0x0e, (byte)0x00, (byte)0x1d, (byte)0x00, (byte)0x01, (byte)0x09,
+(byte)0xa0
+ };
+
+ public static void main(String[] args) throws Exception
+ {
+ try {
+ SourceDebugExtension loader = new SourceDebugExtension();
+ /* The test program creates a class file from the header
+ * stored above and adding the content of a SourceDebugExtension
+ * attribute made of the character 0x02 repeated 68000 times.
+ * This attribute doesn't follow the syntax specified in JSR 45
+ * but it's fine because this test just checks that the JVM is
+ * able to load a class file with a SourceDebugExtension
+ * attribute bigger than 64KB. The JVM doesn't try to
+ * parse the content of the attribute, this work is performed
+ * by the SA or external tools.
+ */
+ byte[] buf = new byte[header.length + attrSize];
+ for(int i=0; i<header.length; i++) {
+ buf[i] = header[i];
+ }
+ for(int i=0; i<attrSize; i++) {
+ buf[header.length+i] = (byte)0x02;
+ }
+ Class c = loader.defineClass("TestProg", buf, 0, buf.length);
+ System.out.println("Test PASSES");
+ } catch(Exception e) {
+ System.out.println("Test FAILS");
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/6294277/Test6294277.sh Wed Jul 05 18:16:35 2017 +0200
@@ -0,0 +1,92 @@
+#
+# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# This code is free software; you can redistribute it and/or modify it
+# 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 Test6294277.sh
+# @bug 6294277
+# @summary java -Xdebug crashes on SourceDebugExtension attribute larger than 64K
+# @run shell Test6294277.sh
+#
+
+
+if [ "${TESTSRC}" = "" ]
+then TESTSRC=.
+fi
+
+if [ "${TESTJAVA}" = "" ]
+then
+ PARENT=`dirname \`which java\``
+ TESTJAVA=`dirname ${PARENT}`
+ echo "TESTJAVA not set, selecting " ${TESTJAVA}
+ echo "If this is incorrect, try setting the variable manually."
+fi
+
+BIT_FLAG=""
+
+# set platform-dependent variables
+OS=`uname -s`
+case "$OS" in
+ SunOS | Linux )
+ NULL=/dev/null
+ PS=":"
+ FS="/"
+ ## for solaris, linux it's HOME
+ FILE_LOCATION=$HOME
+ if [ -f ${FILE_LOCATION}${FS}JDK64BIT -a ${OS} = "SunOS" -a `uname -p`='sparc' ]
+ then
+ BIT_FLAG="-d64"
+ fi
+ ;;
+ Windows_* | Darwin )
+ NULL=NUL
+ PS=";"
+ FS="\\"
+ echo "Test skipped"
+ exit 0
+ ;;
+ * )
+ echo "Unrecognized system!"
+ exit 1;
+ ;;
+esac
+
+cp ${TESTSRC}${FS}*.java .
+
+${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -fullversion
+
+${TESTJAVA}${FS}bin${FS}javac *.java
+
+${TESTJAVA}${FS}bin${FS}java ${BIT_FLAG} -classpath . -Xdebug -Xrunjdwp:transport=dt_socket,address=8888,server=y,suspend=n SourceDebugExtension > test.out 2>&1 &
+
+P_PID=$!
+
+sleep 60
+STATUS=1
+
+grep "Test PASSES" test.out > ${NULL}
+if [ $? = 0 ]; then
+ cat test.out
+ STATUS=0
+fi
+
+exit $STATUS
--- a/hotspot/test/serviceability/ParserTest.java Thu Jul 12 16:47:53 2012 -0700
+++ b/hotspot/test/serviceability/ParserTest.java Wed Jul 05 18:16:35 2017 +0200
@@ -20,6 +20,7 @@
testNanoTime();
testJLong();
testBool();
+ testQuotes();
testMemorySize();
}
@@ -95,6 +96,33 @@
parse(name, "false", "", args);
}
+ public void testQuotes() throws Exception {
+ String name = "name";
+ DiagnosticCommand arg1 = new DiagnosticCommand(name,
+ "desc", DiagnosticArgumentType.STRING,
+ false, null);
+ DiagnosticCommand arg2 = new DiagnosticCommand("arg",
+ "desc", DiagnosticArgumentType.STRING,
+ false, null);
+ DiagnosticCommand[] args = {arg1, arg2};
+
+ // try with a quoted value
+ parse(name, "Recording 1", name + "=\"Recording 1\"", args);
+ // try with a quoted argument
+ parse(name, "myrec", "\"" + name + "\"" + "=myrec", args);
+ // try with both a quoted value and a quoted argument
+ parse(name, "Recording 1", "\"" + name + "\"" + "=\"Recording 1\"", args);
+
+ // now the same thing but with other arguments after
+
+ // try with a quoted value
+ parse(name, "Recording 1", name + "=\"Recording 1\",arg=value", args);
+ // try with a quoted argument
+ parse(name, "myrec", "\"" + name + "\"" + "=myrec,arg=value", args);
+ // try with both a quoted value and a quoted argument
+ parse(name, "Recording 1", "\"" + name + "\"" + "=\"Recording 1\",arg=value", args);
+ }
+
public void testMemorySize() throws Exception {
String name = "name";
String defaultValue = "1024";
--- a/jdk/.hgtags Thu Jul 12 16:47:53 2012 -0700
+++ b/jdk/.hgtags Wed Jul 05 18:16:35 2017 +0200
@@ -168,3 +168,4 @@
db471a7af03168e4441c245b1d9976f720a7cb77 jdk8-b44
b92353a01aa049bc508fc56f0347d5934b7c4390 jdk8-b45
8d2ed9d58453c8049715a72a6d26b6b66b37a94c jdk8-b46
+00b22b23269a57d0bb46c57753be2fe9a9d2c1a3 jdk8-b47
--- a/make/scripts/hgforest.sh Thu Jul 12 16:47:53 2012 -0700
+++ b/make/scripts/hgforest.sh Wed Jul 05 18:16:35 2017 +0200
@@ -98,7 +98,8 @@
(
(
if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
- cline="hg clone ${pull_default}/${i} ${i}"
+ pull_newrepo="`echo ${pull_default}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
+ cline="hg clone ${pull_newrepo} ${i}"
echo "# ${cline}"
( eval "${cline}" )
else
@@ -121,7 +122,8 @@
n=`expr ${n} '+' 1`
(
(
- cline="hg clone ${pull_extra}/${i} ${i}"
+ pull_newextrarepo="`echo ${pull_extra}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
+ cline="hg clone ${pull_newextrarepo} ${i}"
echo "# ${cline}"
( eval "${cline}" )
echo "# exit code $?"