< prev index next >
src/hotspot/share/code/codeHeapState.cpp
Print this page
@@ -115,12 +115,13 @@
#define STRINGSTREAM_FLUSH_LOCKED(termString) \
_outbuf->print("%s", termString);
#endif
-const char blobTypeChar[] = {' ', 'N', 'I', 'X', 'Z', 'U', 'R', '?', 'D', 'T', 'E', 'S', 'A', 'M', 'B', 'L' };
+const char blobTypeChar[] = {' ', 'C', 'N', 'I', 'X', 'Z', 'U', 'R', '?', 'D', 'T', 'E', 'S', 'A', 'M', 'B', 'L' };
const char* blobTypeName[] = {"noType"
+ , "nMethod (under construction)"
, "nMethod (active)"
, "nMethod (inactive)"
, "nMethod (deopt)"
, "nMethod (zombie)"
, "nMethod (unloaded)"
@@ -154,11 +155,12 @@
static bool segment_granules = false;
static unsigned int nBlocks_t1 = 0; // counting "in_use" nmethods only.
static unsigned int nBlocks_t2 = 0; // counting "in_use" nmethods only.
static unsigned int nBlocks_alive = 0; // counting "not_used" and "not_entrant" nmethods only.
static unsigned int nBlocks_dead = 0; // counting "zombie" and "unloaded" methods only.
-static unsigned int nBlocks_unloaded = 0; // counting "unloaded" nmethods only. This is a transien state.
+static unsigned int nBlocks_inconstr = 0; // counting "inconstruction" nmethods only. This is a transient state.
+static unsigned int nBlocks_unloaded = 0; // counting "unloaded" nmethods only. This is a transient state.
static unsigned int nBlocks_stub = 0;
static struct FreeBlk* FreeArray = NULL;
static unsigned int alloc_freeBlocks = 0;
@@ -224,10 +226,11 @@
segment_granules = CodeHeapStatArray[ix].segment_granules;
nBlocks_t1 = CodeHeapStatArray[ix].nBlocks_t1;
nBlocks_t2 = CodeHeapStatArray[ix].nBlocks_t2;
nBlocks_alive = CodeHeapStatArray[ix].nBlocks_alive;
nBlocks_dead = CodeHeapStatArray[ix].nBlocks_dead;
+ nBlocks_inconstr = CodeHeapStatArray[ix].nBlocks_inconstr;
nBlocks_unloaded = CodeHeapStatArray[ix].nBlocks_unloaded;
nBlocks_stub = CodeHeapStatArray[ix].nBlocks_stub;
FreeArray = CodeHeapStatArray[ix].FreeArray;
alloc_freeBlocks = CodeHeapStatArray[ix].alloc_freeBlocks;
TopSizeArray = CodeHeapStatArray[ix].TopSizeArray;
@@ -246,10 +249,11 @@
segment_granules = false;
nBlocks_t1 = 0;
nBlocks_t2 = 0;
nBlocks_alive = 0;
nBlocks_dead = 0;
+ nBlocks_inconstr = 0;
nBlocks_unloaded = 0;
nBlocks_stub = 0;
FreeArray = NULL;
alloc_freeBlocks = 0;
TopSizeArray = NULL;
@@ -272,10 +276,11 @@
CodeHeapStatArray[ix].segment_granules = segment_granules;
CodeHeapStatArray[ix].nBlocks_t1 = nBlocks_t1;
CodeHeapStatArray[ix].nBlocks_t2 = nBlocks_t2;
CodeHeapStatArray[ix].nBlocks_alive = nBlocks_alive;
CodeHeapStatArray[ix].nBlocks_dead = nBlocks_dead;
+ CodeHeapStatArray[ix].nBlocks_inconstr = nBlocks_inconstr;
CodeHeapStatArray[ix].nBlocks_unloaded = nBlocks_unloaded;
CodeHeapStatArray[ix].nBlocks_stub = nBlocks_stub;
CodeHeapStatArray[ix].FreeArray = FreeArray;
CodeHeapStatArray[ix].alloc_freeBlocks = alloc_freeBlocks;
CodeHeapStatArray[ix].TopSizeArray = TopSizeArray;
@@ -552,10 +557,11 @@
//---< reset counters with every aggregation >---
nBlocks_t1 = 0;
nBlocks_t2 = 0;
nBlocks_alive = 0;
nBlocks_dead = 0;
+ nBlocks_inconstr = 0;
nBlocks_unloaded = 0;
nBlocks_stub = 0;
nBlocks_free = 0;
nBlocks_used = 0;
@@ -585,10 +591,11 @@
size_t t2Space = 0;
size_t aliveSpace = 0;
size_t disconnSpace = 0;
size_t notentrSpace = 0;
size_t deadSpace = 0;
+ size_t inconstrSpace = 0;
size_t unloadedSpace = 0;
size_t stubSpace = 0;
size_t freeSpace = 0;
size_t maxFreeSize = 0;
HeapBlock* maxFreeBlock = NULL;
@@ -690,10 +697,14 @@
break;
case nMethod_dead:
nBlocks_dead++;
deadSpace += hb_bytelen;
break;
+ case nMethod_inconstruction:
+ nBlocks_inconstr++;
+ inconstrSpace += hb_bytelen;
+ break;
default:
break;
}
}
@@ -844,10 +855,11 @@
StatArray[ix_beg].t2_age = StatArray[ix_beg].t2_age < compile_id ? compile_id : StatArray[ix_beg].t2_age;
}
StatArray[ix_beg].level = comp_lvl;
StatArray[ix_beg].compiler = cType;
break;
+ case nMethod_inconstruction: // let's count "in construction" nmethods here.
case nMethod_alive:
StatArray[ix_beg].tx_count++;
StatArray[ix_beg].tx_space += (unsigned short)hb_len;
StatArray[ix_beg].tx_age = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age;
StatArray[ix_beg].level = comp_lvl;
@@ -900,10 +912,11 @@
StatArray[ix_beg].level = comp_lvl;
StatArray[ix_beg].compiler = cType;
StatArray[ix_end].level = comp_lvl;
StatArray[ix_end].compiler = cType;
break;
+ case nMethod_inconstruction: // let's count "in construction" nmethods here.
case nMethod_alive:
StatArray[ix_beg].tx_count++;
StatArray[ix_beg].tx_space += (unsigned short)beg_space;
StatArray[ix_beg].tx_age = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age;
@@ -947,10 +960,11 @@
StatArray[ix].t2_age = StatArray[ix].t2_age < compile_id ? compile_id : StatArray[ix].t2_age;
}
StatArray[ix].level = comp_lvl;
StatArray[ix].compiler = cType;
break;
+ case nMethod_inconstruction: // let's count "in construction" nmethods here.
case nMethod_alive:
StatArray[ix].tx_count++;
StatArray[ix].tx_space += (unsigned short)(granule_size>>log2_seg_size);
StatArray[ix].tx_age = StatArray[ix].tx_age < compile_id ? compile_id : StatArray[ix].tx_age;
StatArray[ix].level = comp_lvl;
@@ -969,15 +983,10 @@
}
}
}
}
}
- if (n_methods > 0) {
- avgTemp = hotnessAccumulator/n_methods;
- } else {
- avgTemp = 0;
- }
done = true;
if (!insane) {
// There is a risk for this block (because it contains many print statements) to get
// interspersed with print data from other threads. We take this risk intentionally.
@@ -988,10 +997,11 @@
ast->print_cr(" Tier1 Space = " SIZE_FORMAT_W(8) "k, nBlocks_t1 = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t1Space/(size_t)K, nBlocks_t1, (100.0*t1Space)/size, (100.0*t1Space)/res_size);
ast->print_cr(" Tier2 Space = " SIZE_FORMAT_W(8) "k, nBlocks_t2 = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t2Space/(size_t)K, nBlocks_t2, (100.0*t2Space)/size, (100.0*t2Space)/res_size);
ast->print_cr(" Alive Space = " SIZE_FORMAT_W(8) "k, nBlocks_alive = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", aliveSpace/(size_t)K, nBlocks_alive, (100.0*aliveSpace)/size, (100.0*aliveSpace)/res_size);
ast->print_cr(" disconnected = " SIZE_FORMAT_W(8) "k, nBlocks_disconn = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", disconnSpace/(size_t)K, nBlocks_disconn, (100.0*disconnSpace)/size, (100.0*disconnSpace)/res_size);
ast->print_cr(" not entrant = " SIZE_FORMAT_W(8) "k, nBlocks_notentr = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", notentrSpace/(size_t)K, nBlocks_notentr, (100.0*notentrSpace)/size, (100.0*notentrSpace)/res_size);
+ ast->print_cr(" inconstrSpace = " SIZE_FORMAT_W(8) "k, nBlocks_inconstr = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", inconstrSpace/(size_t)K, nBlocks_inconstr, (100.0*inconstrSpace)/size, (100.0*inconstrSpace)/res_size);
ast->print_cr(" unloadedSpace = " SIZE_FORMAT_W(8) "k, nBlocks_unloaded = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", unloadedSpace/(size_t)K, nBlocks_unloaded, (100.0*unloadedSpace)/size, (100.0*unloadedSpace)/res_size);
ast->print_cr(" deadSpace = " SIZE_FORMAT_W(8) "k, nBlocks_dead = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", deadSpace/(size_t)K, nBlocks_dead, (100.0*deadSpace)/size, (100.0*deadSpace)/res_size);
ast->print_cr(" stubSpace = " SIZE_FORMAT_W(8) "k, nBlocks_stub = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", stubSpace/(size_t)K, nBlocks_stub, (100.0*stubSpace)/size, (100.0*stubSpace)/res_size);
ast->print_cr("ZombieBlocks = %8d. These are HeapBlocks which could not be identified as CodeBlobs.", nBlocks_zomb);
ast->cr();
@@ -1007,13 +1017,19 @@
int reset_val = NMethodSweeper::hotness_counter_reset_val();
double reverse_free_ratio = (res_size > size) ? (double)res_size/(double)(res_size-size) : (double)res_size;
printBox(ast, '-', "Method hotness information at time of this analysis", NULL);
ast->print_cr("Highest possible method temperature: %12d", reset_val);
ast->print_cr("Threshold for method to be considered 'cold': %12.3f", -reset_val + reverse_free_ratio * NmethodSweepActivity);
+ if (n_methods > 0) {
+ avgTemp = hotnessAccumulator/n_methods;
ast->print_cr("min. hotness = %6d", minTemp);
ast->print_cr("avg. hotness = %6d", avgTemp);
ast->print_cr("max. hotness = %6d", maxTemp);
+ } else {
+ avgTemp = 0;
+ ast->print_cr("No hotness data available");
+ }
STRINGSTREAM_FLUSH("\n")
// This loop is intentionally printing directly to "out".
out->print("Verifying collected data...");
size_t granule_segs = granule_size>>log2_seg_size;
@@ -1022,10 +1038,13 @@
out->print_cr("t1_count[%d] = %d", ix, StatArray[ix].t1_count);
}
if (StatArray[ix].t2_count > granule_segs) {
out->print_cr("t2_count[%d] = %d", ix, StatArray[ix].t2_count);
}
+ if (StatArray[ix].tx_count > granule_segs) {
+ out->print_cr("tx_count[%d] = %d", ix, StatArray[ix].tx_count);
+ }
if (StatArray[ix].stub_count > granule_segs) {
out->print_cr("stub_count[%d] = %d", ix, StatArray[ix].stub_count);
}
if (StatArray[ix].dead_count > granule_segs) {
out->print_cr("dead_count[%d] = %d", ix, StatArray[ix].dead_count);
@@ -1034,22 +1053,25 @@
out->print_cr("t1_space[%d] = %d", ix, StatArray[ix].t1_space);
}
if (StatArray[ix].t2_space > granule_segs) {
out->print_cr("t2_space[%d] = %d", ix, StatArray[ix].t2_space);
}
+ if (StatArray[ix].tx_space > granule_segs) {
+ out->print_cr("tx_space[%d] = %d", ix, StatArray[ix].tx_space);
+ }
if (StatArray[ix].stub_space > granule_segs) {
out->print_cr("stub_space[%d] = %d", ix, StatArray[ix].stub_space);
}
if (StatArray[ix].dead_space > granule_segs) {
out->print_cr("dead_space[%d] = %d", ix, StatArray[ix].dead_space);
}
// this cast is awful! I need it because NT/Intel reports a signed/unsigned mismatch.
- if ((size_t)(StatArray[ix].t1_count+StatArray[ix].t2_count+StatArray[ix].stub_count+StatArray[ix].dead_count) > granule_segs) {
- out->print_cr("t1_count[%d] = %d, t2_count[%d] = %d, stub_count[%d] = %d", ix, StatArray[ix].t1_count, ix, StatArray[ix].t2_count, ix, StatArray[ix].stub_count);
+ if ((size_t)(StatArray[ix].t1_count+StatArray[ix].t2_count+StatArray[ix].tx_count+StatArray[ix].stub_count+StatArray[ix].dead_count) > granule_segs) {
+ out->print_cr("t1_count[%d] = %d, t2_count[%d] = %d, tx_count[%d] = %d, stub_count[%d] = %d", ix, StatArray[ix].t1_count, ix, StatArray[ix].t2_count, ix, StatArray[ix].tx_count, ix, StatArray[ix].stub_count);
}
- if ((size_t)(StatArray[ix].t1_space+StatArray[ix].t2_space+StatArray[ix].stub_space+StatArray[ix].dead_space) > granule_segs) {
- out->print_cr("t1_space[%d] = %d, t2_space[%d] = %d, stub_space[%d] = %d", ix, StatArray[ix].t1_space, ix, StatArray[ix].t2_space, ix, StatArray[ix].stub_space);
+ if ((size_t)(StatArray[ix].t1_space+StatArray[ix].t2_space+StatArray[ix].tx_space+StatArray[ix].stub_space+StatArray[ix].dead_space) > granule_segs) {
+ out->print_cr("t1_space[%d] = %d, t2_space[%d] = %d, tx_space[%d] = %d, stub_space[%d] = %d", ix, StatArray[ix].t1_space, ix, StatArray[ix].t2_space, ix, StatArray[ix].tx_space, ix, StatArray[ix].stub_space);
}
}
// This loop is intentionally printing directly to "out".
if (used_topSizeBlocks > 0) {
@@ -1129,11 +1151,11 @@
done = true;
}
if (!done || (nBlocks_free == 0)) {
if (nBlocks_free == 0) {
- printBox(ast, '-', "no free blocks found in", heapName);
+ printBox(ast, '-', "no free blocks found in ", heapName);
} else if (!done) {
ast->print_cr("Free block count mismatch could not be resolved.");
ast->print_cr("Try to run \"aggregate\" function to update counters");
}
STRINGSTREAM_FLUSH("")
@@ -1261,11 +1283,12 @@
ast->print("%5d", nm->hotness_counter());
//---< name and signature >---
ast->fill_to(67+6);
if (nm->is_in_use()) {blob_name = nm->method()->name_and_sig_as_C_string(); }
if (nm->is_not_entrant()) {blob_name = nm->method()->name_and_sig_as_C_string(); }
- if (nm->is_zombie()) {ast->print("%14s", " zombie method"); }
+ if (nm->is_not_installed()) {ast->print("%s", " not (yet) installed method "); }
+ if (nm->is_zombie()) {ast->print("%s", " zombie method "); }
ast->print("%s", blob_name);
} else {
//---< block size in hex >---
ast->print(PTR32_FORMAT, (unsigned int)(TopSizeArray[i].len<<log2_seg_size));
ast->print("(" SIZE_FORMAT_W(4) "K)", (TopSizeArray[i].len<<log2_seg_size)/K);
@@ -1655,11 +1678,11 @@
}
}
{
if (nBlocks_alive > 0) {
- printBox(ast, '-', "not_used/not_entrant nMethod count only, 0x1..0xf. '*' indicates >= 16 blocks, ' ' indicates empty", NULL);
+ printBox(ast, '-', "not_used/not_entrant/not_installed nMethod count only, 0x1..0xf. '*' indicates >= 16 blocks, ' ' indicates empty", NULL);
STRINGSTREAM_FLUSH_LOCKED("")
granules_per_line = 128;
for (unsigned int ix = 0; ix < alloc_granules; ix++) {
print_line_delim(out, ast, low_bound, ix, granules_per_line);
@@ -1844,11 +1867,11 @@
}
}
{
if (nBlocks_alive > 0) {
- printBox(ast, '-', "not_used/not_entrant space consumption. ' ' indicates empty, '*' indicates full", NULL);
+ printBox(ast, '-', "not_used/not_entrant/not_installed space consumption. ' ' indicates empty, '*' indicates full", NULL);
granules_per_line = 128;
for (unsigned int ix = 0; ix < alloc_granules; ix++) {
print_line_delim(out, ast, low_bound, ix, granules_per_line);
if (segment_granules && StatArray[ix].tx_space > 0) {
@@ -2014,11 +2037,11 @@
}
}
{
if (nBlocks_alive > 0) {
- printBox(ast, '-', "not_used/not_entrant age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
+ printBox(ast, '-', "not_used/not_entrant/not_installed age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
STRINGSTREAM_FLUSH_LOCKED("")
granules_per_line = 128;
for (unsigned int ix = 0; ix < alloc_granules; ix++) {
print_line_delim(out, ast, low_bound, ix, granules_per_line);
@@ -2144,11 +2167,11 @@
ast->fill_to(33);
// this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
nmethod* nm = this_blob->as_nmethod_or_null();
Method* method = (nm == NULL) ? NULL : nm->method(); // may be uninitialized, i.e. != NULL, but invalid
- if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) &&
+ if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) && (cbType != nMethod_inconstruction) &&
is_readable_pointer(method) && is_readable_pointer(method->constants())) {
ResourceMark rm;
//---< collect all data to locals as quickly as possible >---
unsigned int total_size = nm->total_size();
int hotness = nm->hotness_counter();
@@ -2356,15 +2379,16 @@
if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob;
if (cb->is_buffer_blob()) return bufferBlob;
nmethod* nm = cb->as_nmethod_or_null();
if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb.
+ if (nm->is_not_installed()) return nMethod_inconstruction;
if (nm->is_zombie()) return nMethod_dead;
if (nm->is_unloaded()) return nMethod_unloaded;
+ if (nm->is_in_use()) return nMethod_inuse;
if (nm->is_alive() && !(nm->is_not_entrant())) return nMethod_notused;
if (nm->is_alive()) return nMethod_alive;
- if (nm->is_in_use()) return nMethod_inuse;
return nMethod_dead;
}
}
return noType;
}
< prev index next >